blob: 55913adc323581d828007edf69ba027227a94b72 [file] [log] [blame]
import re
import struct
import time
import uuid
import pytest
import logging
import codecs
from thrift.protocol import TBinaryProtocol
from thrift.Thrift import TApplicationException
from thrift.transport import TSocket, TTransport
from tools.assertions import assert_length_equal
from tools.misc import ImmutableMapping
from dtest_setup_overrides import DTestSetupOverrides
from dtest import Tester
from thrift_bindings.thrift010 import Cassandra
from thrift_bindings.thrift010.Cassandra import (CfDef, Column, ColumnDef,
ColumnOrSuperColumn, ColumnParent,
ColumnPath, ColumnSlice,
ConsistencyLevel, CounterColumn,
Deletion, IndexExpression,
IndexOperator, IndexType,
InvalidRequestException, KeyRange,
KeySlice, KsDef, MultiSliceRequest,
Mutation, NotFoundException,
SlicePredicate, SliceRange,
SuperColumn)
from tools.assertions import (assert_all, assert_none, assert_one)
MAX_TTL = 20 * 365 * 24 * 60 * 60 # 20 years in seconds
since = pytest.mark.since
logger = logging.getLogger(__name__)
utf8encoder = codecs.getencoder('utf-8')
def utf8encode(str):
return utf8encoder(str)[0]
def get_thrift_client(host='127.0.0.1', port=9160):
socket = TSocket.TSocket(host, port)
transport = TTransport.TFramedTransport(socket)
protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = Cassandra.Client(protocol)
client.transport = transport
return client
client = None
pid_fname = "system_test.pid"
def pid():
return int(open(pid_fname).read())
@since('2.0', max_version='4')
class TestThrift(Tester):
@pytest.fixture(scope='function', autouse=True)
def fixture_dtest_setup_overrides(self, dtest_config):
dtest_setup_overrides = DTestSetupOverrides()
"""
@jira_ticket CASSANDRA-7653
"""
dtest_setup_overrides.cluster_options = ImmutableMapping(
{'partitioner': 'org.apache.cassandra.dht.ByteOrderedPartitioner',
'start_rpc': 'true'})
return dtest_setup_overrides
@pytest.fixture(scope='function', autouse=True)
def fixture_set_cluster_settings(self, fixture_dtest_setup):
fixture_dtest_setup.cluster.populate(1)
node1, = fixture_dtest_setup.cluster.nodelist()
# If vnodes are not used, we must set our own initial_token
# Because ccm will not set a hex token for ByteOrderedPartitioner
# automatically. It does not matter what token we set as we only
# ever use one node.
if not fixture_dtest_setup.dtest_config.use_vnodes:
node1.set_configuration_options(values={'initial_token': 'abcd'})
# CASSANDRA-14092 - prevent max ttl tests from failing
fixture_dtest_setup.cluster.start(jvm_args=['-Dcassandra.expiration_date_overflow_policy=CAP',
'-Dcassandra.expiration_overflow_warning_interval_minutes=0'])
fixture_dtest_setup.cluster.nodelist()[0].watch_log_for("Listening for thrift clients") # Wait for the thrift port to open
time.sleep(0.1)
# this is ugly, but the whole test module is written against a global client
global client
client = get_thrift_client()
client.transport.open()
self.define_schema()
yield client
client.transport.close()
def define_schema(self):
keyspace1 = Cassandra.KsDef('Keyspace1', 'org.apache.cassandra.locator.SimpleStrategy', {'replication_factor': '1'},
cf_defs=[
Cassandra.CfDef('Keyspace1', 'Standard1'),
Cassandra.CfDef('Keyspace1', 'Standard2'),
Cassandra.CfDef('Keyspace1', 'Standard3', column_metadata=[Cassandra.ColumnDef(utf8encode('c1'), 'AsciiType'), Cassandra.ColumnDef(utf8encode('c2'), 'AsciiType')]),
Cassandra.CfDef('Keyspace1', 'Standard4', column_metadata=[Cassandra.ColumnDef(utf8encode('c1'), 'AsciiType')]),
Cassandra.CfDef('Keyspace1', 'StandardLong1', comparator_type='LongType'),
Cassandra.CfDef('Keyspace1', 'StandardInteger1', comparator_type='IntegerType'),
Cassandra.CfDef('Keyspace1', 'StandardComposite', comparator_type='CompositeType(AsciiType, AsciiType)'),
Cassandra.CfDef('Keyspace1', 'Super1', column_type='Super', subcomparator_type='LongType'),
Cassandra.CfDef('Keyspace1', 'Super2', column_type='Super', subcomparator_type='LongType'),
Cassandra.CfDef('Keyspace1', 'Super3', column_type='Super', comparator_type='LongType', subcomparator_type='UTF8Type'),
Cassandra.CfDef('Keyspace1', 'Counter1', default_validation_class='CounterColumnType'),
Cassandra.CfDef('Keyspace1', 'SuperCounter1', column_type='Super', default_validation_class='CounterColumnType'),
Cassandra.CfDef('Keyspace1', 'Indexed1', column_metadata=[Cassandra.ColumnDef(utf8encode('birthdate'), 'LongType', Cassandra.IndexType.KEYS, 'birthdate_index')]),
Cassandra.CfDef('Keyspace1', 'Indexed2', comparator_type='TimeUUIDType', column_metadata=[Cassandra.ColumnDef(uuid.UUID('00000000-0000-1000-0000-000000000000').bytes, 'LongType', Cassandra.IndexType.KEYS)]),
Cassandra.CfDef('Keyspace1', 'Indexed3', comparator_type='TimeUUIDType', column_metadata=[Cassandra.ColumnDef(uuid.UUID('00000000-0000-1000-0000-000000000000').bytes, 'UTF8Type', Cassandra.IndexType.KEYS)]),
Cassandra.CfDef('Keyspace1', 'Indexed4', column_metadata=[Cassandra.ColumnDef(utf8encode('a'), 'LongType', Cassandra.IndexType.KEYS, 'a_index'), Cassandra.ColumnDef(utf8encode('z'), 'UTF8Type')]),
Cassandra.CfDef('Keyspace1', 'Expiring', default_time_to_live=2),
Cassandra.CfDef('Keyspace1', 'ExpiringMaxTTL', default_time_to_live=MAX_TTL)
])
keyspace2 = Cassandra.KsDef('Keyspace2', 'org.apache.cassandra.locator.SimpleStrategy', {'replication_factor': '1'},
cf_defs=[
Cassandra.CfDef('Keyspace2', 'Standard1'),
Cassandra.CfDef('Keyspace2', 'Standard3'),
Cassandra.CfDef('Keyspace2', 'Super3', column_type='Super', subcomparator_type='BytesType'),
Cassandra.CfDef('Keyspace2', 'Super4', column_type='Super', subcomparator_type='TimeUUIDType'), ])
for ks in [keyspace1, keyspace2]:
client.system_add_keyspace(ks)
def i64(n):
return _i64(n)
def i32(n):
return _i32(n)
def i16(n):
return _i16(n)
def composite(item1, item2=None, eoc=b'\x00'):
if isinstance(item1, str):
item1 = utf8encode(item1)
if isinstance(item2, str):
item2 = utf8encode(item2)
if isinstance(eoc, str):
eoc = utf8encode(eoc)
packed = _i16(len(item1)) + item1 + eoc
if item2 is not None:
packed += _i16(len(item2)) + item2
packed += eoc
return packed
def _i64(n):
return struct.pack('>q', n) # big endian = network order
def _i32(n):
return struct.pack('>i', n) # big endian = network order
def _i16(n):
return struct.pack('>h', n) # big endian = network order
_SIMPLE_COLUMNS = [Column(utf8encode('c1'), utf8encode('value1'), 0),
Column(utf8encode('c2'), utf8encode('value2'), 0)]
_SUPER_COLUMNS = [SuperColumn(name=utf8encode('sc1'), columns=[Column(_i64(4), utf8encode('value4'), 0)]),
SuperColumn(name=utf8encode('sc2'), columns=[Column(_i64(5), utf8encode('value5'), 0),
Column(_i64(6), utf8encode('value6'), 0)])]
def _assert_column(column_family, key, column, value, ts=0):
if isinstance(key, str):
key = utf8encode(key)
if isinstance(value, str):
value = utf8encode(value)
try:
assert client.get(key, ColumnPath(column_family, column=column), ConsistencyLevel.ONE).column == Column(column, value, ts)
except NotFoundException:
raise Exception('expected %s:%s:%s:%s, but was not present' % (column_family, key, column, value))
def _assert_columnpath_exists(key, column_path):
if isinstance(key, str):
key = utf8encode(key)
try:
assert client.get(key, column_path, ConsistencyLevel.ONE)
except NotFoundException:
raise Exception('expected %s with %s but was not present.' % (key, column_path))
def _assert_no_columnpath(key, column_path):
if isinstance(key, str):
key = utf8encode(key)
try:
client.get(key, column_path, ConsistencyLevel.ONE)
assert False, ('columnpath %s existed in %s when it should not' % (column_path, key))
except NotFoundException:
assert True, 'column did not exist'
def _insert_simple():
return _insert_multi([utf8encode('key1')])
def _insert_multi(keys):
CL = ConsistencyLevel.ONE
for key in keys:
if isinstance(key, str):
key = utf8encode(key)
client.insert(key, ColumnParent('Standard1'), Column(utf8encode('c1'), utf8encode('value1'), 0), CL)
client.insert(key, ColumnParent('Standard1'), Column(utf8encode('c2'), utf8encode('value2'), 0), CL)
def _insert_batch():
cfmap = {'Standard1': [Mutation(ColumnOrSuperColumn(c)) for c in _SIMPLE_COLUMNS],
'Standard2': [Mutation(ColumnOrSuperColumn(c)) for c in _SIMPLE_COLUMNS]}
client.batch_mutate({utf8encode('key1'): cfmap}, ConsistencyLevel.ONE)
def _big_slice(key, column_parent):
if isinstance(key, str):
key = utf8encode(key)
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1000))
return client.get_slice(key, column_parent, p, ConsistencyLevel.ONE)
def _big_multislice(keys, column_parent):
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1000))
return client.multiget_slice(keys, column_parent, p, ConsistencyLevel.ONE)
def _verify_batch():
_verify_simple()
L = [result.column
for result in _big_slice(utf8encode('key1'), ColumnParent('Standard2'))]
assert L == _SIMPLE_COLUMNS, L
def _verify_simple():
assert client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('c1')), ConsistencyLevel.ONE).column == Column(utf8encode('c1'), utf8encode('value1'), 0)
L = [result.column
for result in _big_slice(utf8encode('key1'), ColumnParent('Standard1'))]
assert L == _SIMPLE_COLUMNS, L
def _insert_super(key='key1'):
if isinstance(key, str):
key = utf8encode(key)
client.insert(key, ColumnParent('Super1', utf8encode('sc1')), Column(_i64(4), utf8encode('value4'), 0), ConsistencyLevel.ONE)
client.insert(key, ColumnParent('Super1', utf8encode('sc2')), Column(_i64(5), utf8encode('value5'), 0), ConsistencyLevel.ONE)
client.insert(key, ColumnParent('Super1', utf8encode('sc2')), Column(_i64(6), utf8encode('value6'), 0), ConsistencyLevel.ONE)
def _insert_range():
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c1'), utf8encode('value1'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c2'), utf8encode('value2'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c3'), utf8encode('value3'), 0), ConsistencyLevel.ONE)
def _verify_range():
p = SlicePredicate(slice_range=SliceRange(utf8encode('c1'), utf8encode('c2'), False, 1000))
result = client.get_slice(utf8encode('key1'), ColumnParent('Standard1'), p, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].column.name == utf8encode('c1')
assert result[1].column.name == utf8encode('c2')
p = SlicePredicate(slice_range=SliceRange(utf8encode('c3'), utf8encode('c2'), True, 1000))
result = client.get_slice(utf8encode('key1'), ColumnParent('Standard1'), p, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].column.name == utf8encode('c3')
assert result[1].column.name == utf8encode('c2')
p = SlicePredicate(slice_range=SliceRange(utf8encode('a'), utf8encode('z'), False, 1000))
result = client.get_slice(utf8encode('key1'), ColumnParent('Standard1'), p, ConsistencyLevel.ONE)
assert len(result) == 3, result
p = SlicePredicate(slice_range=SliceRange(utf8encode('a'), utf8encode('z'), False, 2))
result = client.get_slice(utf8encode('key1'), ColumnParent('Standard1'), p, ConsistencyLevel.ONE)
assert len(result) == 2, result
def _set_keyspace(keyspace):
client.set_keyspace(keyspace)
def _insert_super_range():
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc1')), Column(_i64(4), utf8encode('value4'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), Column(_i64(5), utf8encode('value5'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), Column(_i64(6), utf8encode('value6'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc3')), Column(_i64(7), utf8encode('value7'), 0), ConsistencyLevel.ONE)
time.sleep(0.1)
def _verify_super_range():
p = SlicePredicate(slice_range=SliceRange(utf8encode('sc2'), utf8encode('sc3'), False, 2))
result = client.get_slice(utf8encode('key1'), ColumnParent('Super1'), p, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].super_column.name == utf8encode('sc2')
assert result[1].super_column.name == utf8encode('sc3')
p = SlicePredicate(slice_range=SliceRange(utf8encode('sc3'), utf8encode('sc2'), True, 2))
result = client.get_slice(utf8encode('key1'), ColumnParent('Super1'), p, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].super_column.name == utf8encode('sc3')
assert result[1].super_column.name == utf8encode('sc2')
def _verify_super(supercf='Super1', key='key1'):
if isinstance(key, str):
key = utf8encode(key)
assert client.get(key, ColumnPath(supercf, utf8encode('sc1'), _i64(4)), ConsistencyLevel.ONE).column == Column(_i64(4), utf8encode('value4'), 0)
slice = [result.super_column
for result in _big_slice(key, ColumnParent('Super1'))]
assert slice == _SUPER_COLUMNS, slice
def _expect_exception(fn, type_):
try:
r = fn()
except type_ as t:
return t
else:
raise Exception('expected %s; got %s' % (type_.__name__, r))
def _expect_missing(fn):
_expect_exception(fn, NotFoundException)
def get_range_slice(client, parent, predicate, start, end, count, cl, row_filter=None):
kr = KeyRange(start, end, count=count, row_filter=row_filter)
return client.get_range_slices(parent, predicate, kr, cl)
def _insert_six_columns(key='abc'):
if isinstance(key, str):
key = utf8encode(key)
CL = ConsistencyLevel.ONE
client.insert(key, ColumnParent('Standard1'), Column(utf8encode('a'), utf8encode('1'), 0), CL)
client.insert(key, ColumnParent('Standard1'), Column(utf8encode('b'), utf8encode('2'), 0), CL)
client.insert(key, ColumnParent('Standard1'), Column(utf8encode('c'), utf8encode('3'), 0), CL)
client.insert(key, ColumnParent('Standard1'), Column(utf8encode('d'), utf8encode('4'), 0), CL)
client.insert(key, ColumnParent('Standard1'), Column(utf8encode('e'), utf8encode('5'), 0), CL)
client.insert(key, ColumnParent('Standard1'), Column(utf8encode('f'), utf8encode('6'), 0), CL)
def _big_multi_slice(key='abc'):
if isinstance(key, str):
key = utf8encode(key)
c1 = ColumnSlice()
c1.start = utf8encode('a')
c1.finish = utf8encode('c')
c2 = ColumnSlice()
c2.start = utf8encode('e')
c2.finish = utf8encode('f')
m = MultiSliceRequest()
m.key = key
m.column_parent = ColumnParent('Standard1')
m.column_slices = [c1, c2]
m.reversed = False
m.count = 10
m.consistency_level = ConsistencyLevel.ONE
return client.get_multi_slice(m)
_MULTI_SLICE_COLUMNS = [Column(utf8encode('a'), utf8encode('1'), 0), Column(utf8encode('b'), utf8encode('2'), 0), Column(utf8encode('c'), utf8encode('3'), 0), Column(utf8encode('e'), utf8encode('5'), 0), Column(utf8encode('f'), utf8encode('6'), 0)]
@since('2.0', max_version='4')
class TestMutations(TestThrift):
def truncate_all(self, *table_names):
for table in table_names:
client.truncate(table)
def test_insert(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
_insert_simple()
_verify_simple()
def test_empty_slice(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard2', 'Super1')
assert _big_slice(utf8encode('key1'), ColumnParent('Standard2')) == []
assert _big_slice(utf8encode('key1'), ColumnParent('Super1')) == []
def test_cas(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Standard3', 'Standard4')
def cas(expected, updates, column_family):
return client.cas(utf8encode('key1'), column_family, expected, updates, ConsistencyLevel.SERIAL, ConsistencyLevel.QUORUM)
def test_cas_operations(first_columns, second_columns, column_family):
# partition should be empty, so cas expecting any existing values should fail
cas_result = cas(first_columns, first_columns, column_family)
assert not cas_result.success
assert len(cas_result.current_values) == 0, cas_result
# cas of empty columns -> first_columns should succeed
# and the reading back from the table should match first_columns
assert cas([], first_columns, column_family).success
result = [cosc.column for cosc in _big_slice(utf8encode('key1'), ColumnParent(column_family))]
# CAS will use its own timestamp, so we can't just compare result == _SIMPLE_COLUMNS
assert dict((c.name, c.value) for c in result) == dict((ex.name, ex.value) for ex in first_columns)
# now that the partition has been updated, repeating the
# operation which expects it to be empty should not succeed
cas_result = cas([], first_columns, column_family)
assert not cas_result.success
# When we CAS for non-existence, current_values is the first live column of the row
assert dict((c.name, c.value) for c in cas_result.current_values) == {first_columns[0].name: first_columns[0].value}, cas_result
# CL.SERIAL for reads
assert client.get(utf8encode('key1'), ColumnPath(column_family, column=first_columns[0].name), ConsistencyLevel.SERIAL).column.value == first_columns[0].value
# cas first_columns -> second_columns should succeed
assert cas(first_columns, second_columns, column_family).success
# as before, an operation with an incorrect expectation should fail
cas_result = cas(first_columns, second_columns, column_family)
assert not cas_result.success
updated_columns = [Column(utf8encode('c1'), utf8encode('value101'), 1),
Column(utf8encode('c2'), utf8encode('value102'), 1)]
logger.debug("Testing CAS operations on dynamic cf")
test_cas_operations(_SIMPLE_COLUMNS, updated_columns, 'Standard1')
logger.debug("Testing CAS operations on static cf")
test_cas_operations(_SIMPLE_COLUMNS, updated_columns, 'Standard3')
logger.debug("Testing CAS on mixed static/dynamic cf")
test_cas_operations(_SIMPLE_COLUMNS, updated_columns, 'Standard4')
def test_missing_super(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Super1', utf8encode('sc1'), _i64(1)), ConsistencyLevel.ONE))
_insert_super()
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Super1', utf8encode('sc1'), _i64(1)), ConsistencyLevel.ONE))
def test_count(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Standard2', 'Super1')
_insert_simple()
_insert_super()
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1000))
assert client.get_count(utf8encode('key1'), ColumnParent('Standard2'), p, ConsistencyLevel.ONE) == 0
assert client.get_count(utf8encode('key1'), ColumnParent('Standard1'), p, ConsistencyLevel.ONE) == 2
assert client.get_count(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), p, ConsistencyLevel.ONE) == 2
assert client.get_count(utf8encode('key1'), ColumnParent('Super1'), p, ConsistencyLevel.ONE) == 2
# Let's make that a little more interesting
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c3'), utf8encode('value3'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c4'), utf8encode('value4'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c5'), utf8encode('value5'), 0), ConsistencyLevel.ONE)
p = SlicePredicate(slice_range=SliceRange(utf8encode('c2'), utf8encode('c4'), False, 1000))
assert client.get_count(utf8encode('key1'), ColumnParent('Standard1'), p, ConsistencyLevel.ONE) == 3
def test_count_paging(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
_insert_simple()
# Exercise paging
column_parent = ColumnParent('Standard1')
# Paging for small columns starts at 1024 columns
columns_to_insert = [Column(utf8encode('c%d' % (i,)), utf8encode('value%d' % (i,)), 0) for i in range(3, 1026)]
cfmap = {'Standard1': [Mutation(ColumnOrSuperColumn(c)) for c in columns_to_insert]}
client.batch_mutate({utf8encode('key1') : cfmap}, ConsistencyLevel.ONE)
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 2000))
assert client.get_count(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE) == 1025
# Ensure that the count limit isn't clobbered
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 10))
assert client.get_count(utf8encode('key1'), ColumnParent('Standard1'), p, ConsistencyLevel.ONE) == 10
# test get_count() to work correctly with 'count' settings around page size (CASSANDRA-4833)
def test_count_around_page_size(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
def slice_predicate(count):
return SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, count))
key = utf8encode('key1')
parent = ColumnParent('Standard1')
cl = ConsistencyLevel.ONE
for i in range(0, 3050):
client.insert(key, parent, Column(utf8encode(str(i)), utf8encode(''), 0), cl)
# same as page size
assert client.get_count(key, parent, slice_predicate(1024), cl) == 1024
# 1 above page size
assert client.get_count(key, parent, slice_predicate(1025), cl) == 1025
# above number or columns
assert client.get_count(key, parent, slice_predicate(4000), cl) == 3050
# same as number of columns
assert client.get_count(key, parent, slice_predicate(3050), cl) == 3050
# 1 above number of columns
assert client.get_count(key, parent, slice_predicate(3051), cl) == 3050
def test_super_insert(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
_insert_super()
_verify_super()
def test_super_get(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
_insert_super()
result = client.get(utf8encode('key1'), ColumnPath('Super1', utf8encode('sc2')), ConsistencyLevel.ONE).super_column
assert result == _SUPER_COLUMNS[1], result
def test_super_subcolumn_limit(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
_insert_super()
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1))
column_parent = ColumnParent('Super1', utf8encode('sc2'))
slice = [result.column
for result in client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE)]
assert slice == [Column(_i64(5), utf8encode('value5'), 0)], slice
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), True, 1))
slice = [result.column
for result in client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE)]
assert slice == [Column(_i64(6), utf8encode('value6'), 0)], slice
def test_long_order(self):
_set_keyspace('Keyspace1')
self.truncate_all('StandardLong1')
def long_xrange(start, stop, step):
i = start
while i < stop:
yield i
i += step
L = []
for i in long_xrange(0, 104294967296, 429496729):
name = _i64(i)
client.insert(utf8encode('key1'), ColumnParent('StandardLong1'), Column(name, utf8encode('v'), 0), ConsistencyLevel.ONE)
L.append(name)
slice = [result.column.name for result in _big_slice(utf8encode('key1'), ColumnParent('StandardLong1'))]
assert slice == L, slice
def test_integer_order(self):
_set_keyspace('Keyspace1')
self.truncate_all('StandardInteger1')
def long_xrange(start, stop, step):
i = start
while i >= stop:
yield i
i -= step
L = []
for i in long_xrange(104294967296, 0, 429496729):
name = _i64(i)
client.insert(utf8encode('key1'), ColumnParent('StandardInteger1'), Column(name, utf8encode('v'), 0), ConsistencyLevel.ONE)
L.append(name)
slice = [result.column.name for result in _big_slice(utf8encode('key1'), ColumnParent('StandardInteger1'))]
L.sort()
assert slice == L, slice
def test_time_uuid(self):
_set_keyspace('Keyspace2')
self.truncate_all('Super4')
import uuid
L = []
# 100 isn't enough to fail reliably if the comparator is borked
for i in range(500):
L.append(uuid.uuid1())
client.insert(utf8encode('key1'), ColumnParent('Super4', utf8encode('sc1')), Column(L[-1].bytes, utf8encode('value%s' % i), i), ConsistencyLevel.ONE)
slice = _big_slice(utf8encode('key1'), ColumnParent('Super4', utf8encode('sc1')))
assert len(slice) == 500, len(slice)
for i in range(500):
u = slice[i].column
assert u.value == utf8encode('value%s' % i)
assert u.name == L[i].bytes
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), True, 1))
column_parent = ColumnParent('Super4', utf8encode('sc1'))
slice = [result.column
for result in client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE)]
assert slice == [Column(L[-1].bytes, utf8encode('value499'), 499)], slice
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), L[2].bytes, False, 1000))
column_parent = ColumnParent('Super4', utf8encode('sc1'))
slice = [result.column
for result in client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE)]
assert slice == [Column(L[0].bytes, utf8encode('value0'), 0),
Column(L[1].bytes, utf8encode('value1'), 1),
Column(L[2].bytes, utf8encode('value2'), 2)], slice
p = SlicePredicate(slice_range=SliceRange(L[2].bytes, utf8encode(''), True, 1000))
column_parent = ColumnParent('Super4', utf8encode('sc1'))
slice = [result.column
for result in client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE)]
assert slice == [Column(L[2].bytes, utf8encode('value2'), 2),
Column(L[1].bytes, utf8encode('value1'), 1),
Column(L[0].bytes, utf8encode('value0'), 0)], slice
p = SlicePredicate(slice_range=SliceRange(L[2].bytes, utf8encode(''), False, 1))
column_parent = ColumnParent('Super4', utf8encode('sc1'))
slice = [result.column
for result in client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE)]
assert slice == [Column(L[2].bytes, utf8encode('value2'), 2)], slice
def test_long_remove(self):
_set_keyspace('Keyspace1')
self.truncate_all('StandardLong1')
column_parent = ColumnParent('StandardLong1')
sp = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1))
for i in range(10):
parent = ColumnParent('StandardLong1')
client.insert(utf8encode('key1'), parent, Column(_i64(i), utf8encode('value1'), 10 * i), ConsistencyLevel.ONE)
client.remove(utf8encode('key1'), ColumnPath('StandardLong1'), 10 * i + 1, ConsistencyLevel.ONE)
slice = client.get_slice(utf8encode('key1'), column_parent, sp, ConsistencyLevel.ONE)
assert slice == [], slice
# resurrect
client.insert(utf8encode('key1'), parent, Column(_i64(i), utf8encode('value2'), 10 * i + 2), ConsistencyLevel.ONE)
slice = [result.column
for result in client.get_slice(utf8encode('key1'), column_parent, sp, ConsistencyLevel.ONE)]
assert slice == [Column(_i64(i), utf8encode('value2'), 10 * i + 2)], (slice, i)
def test_integer_remove(self):
_set_keyspace('Keyspace1')
self.truncate_all('StandardInteger1')
column_parent = ColumnParent('StandardInteger1')
sp = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1))
for i in range(10):
parent = ColumnParent('StandardInteger1')
client.insert(utf8encode('key1'), parent, Column(_i64(i), utf8encode('value1'), 10 * i), ConsistencyLevel.ONE)
client.remove(utf8encode('key1'), ColumnPath('StandardInteger1'), 10 * i + 1, ConsistencyLevel.ONE)
slice = client.get_slice(utf8encode('key1'), column_parent, sp, ConsistencyLevel.ONE)
assert slice == [], slice
# resurrect
client.insert(utf8encode('key1'), parent, Column(_i64(i), utf8encode('value2'), 10 * i + 2), ConsistencyLevel.ONE)
slice = [result.column
for result in client.get_slice(utf8encode('key1'), column_parent, sp, ConsistencyLevel.ONE)]
assert slice == [Column(_i64(i), utf8encode('value2'), 10 * i + 2)], (slice, i)
def test_batch_insert(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Standard2')
_insert_batch()
_verify_batch()
def test_batch_mutate_standard_columns(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Standard2')
column_families = ['Standard1', 'Standard2']
keys = [utf8encode('key_%d' % i) for i in range(27, 32)]
mutations = [Mutation(ColumnOrSuperColumn(c)) for c in _SIMPLE_COLUMNS]
mutation_map = dict((column_family, mutations) for column_family in column_families)
keyed_mutations = dict((key, mutation_map) for key in keys)
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
for column_family in column_families:
for key in keys:
_assert_column(column_family, key, utf8encode('c1'), utf8encode('value1'))
def test_batch_mutate_remove_standard_columns(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Standard2')
column_families = ['Standard1', 'Standard2']
keys = [utf8encode('key_%d' % i) for i in range(11, 21)]
_insert_multi(keys)
mutations = [Mutation(deletion=Deletion(20, predicate=SlicePredicate(column_names=[c.name]))) for c in _SIMPLE_COLUMNS]
mutation_map = dict((column_family, mutations) for column_family in column_families)
keyed_mutations = dict((key, mutation_map) for key in keys)
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
for column_family in column_families:
for c in _SIMPLE_COLUMNS:
for key in keys:
_assert_no_columnpath(key, ColumnPath(column_family, column=c.name))
def test_batch_mutate_remove_standard_row(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Standard2')
column_families = ['Standard1', 'Standard2']
keys = [utf8encode('key_%d' % i) for i in range(11, 21)]
_insert_multi(keys)
mutations = [Mutation(deletion=Deletion(20))]
mutation_map = dict((column_family, mutations) for column_family in column_families)
keyed_mutations = dict((key, mutation_map) for key in keys)
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
for column_family in column_families:
for c in _SIMPLE_COLUMNS:
for key in keys:
_assert_no_columnpath(key, ColumnPath(column_family, column=c.name))
def test_batch_mutate_remove_super_columns_with_standard_under(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1', 'Super2')
column_families = ['Super1', 'Super2']
keys = [utf8encode('key_%d' % i) for i in range(11, 21)]
_insert_super()
mutations = []
for sc in _SUPER_COLUMNS:
names = []
for c in sc.columns:
names.append(c.name)
mutations.append(Mutation(deletion=Deletion(20, super_column=c.name, predicate=SlicePredicate(column_names=names))))
mutation_map = dict((column_family, mutations) for column_family in column_families)
keyed_mutations = dict((key, mutation_map) for key in keys)
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
for column_family in column_families:
for sc in _SUPER_COLUMNS:
for c in sc.columns:
for key in keys:
_assert_no_columnpath(key, ColumnPath(column_family, super_column=sc.name, column=c.name))
def test_batch_mutate_remove_super_columns_with_none_given_underneath(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
keys = [utf8encode('key_%d' % i) for i in range(17, 21)]
for key in keys:
_insert_super(key)
mutations = []
for sc in _SUPER_COLUMNS:
mutations.append(Mutation(deletion=Deletion(20,
super_column=sc.name)))
mutation_map = {'Super1': mutations}
keyed_mutations = dict((key, mutation_map) for key in keys)
# Sanity check
for sc in _SUPER_COLUMNS:
for key in keys:
_assert_columnpath_exists(key, ColumnPath('Super1', super_column=sc.name))
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
for sc in _SUPER_COLUMNS:
for c in sc.columns:
for key in keys:
_assert_no_columnpath(key, ColumnPath('Super1', super_column=sc.name))
def test_batch_mutate_remove_super_columns_entire_row(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
keys = [utf8encode('key_%d' % i) for i in range(17, 21)]
for key in keys:
_insert_super(key)
mutations = []
mutations.append(Mutation(deletion=Deletion(20)))
mutation_map = {'Super1': mutations}
keyed_mutations = dict((key, mutation_map) for key in keys)
# Sanity check
for sc in _SUPER_COLUMNS:
for key in keys:
_assert_columnpath_exists(key, ColumnPath('Super1', super_column=sc.name))
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
for sc in _SUPER_COLUMNS:
for key in keys:
_assert_no_columnpath(key, ColumnPath('Super1', super_column=sc.name))
# known failure: see CASSANDRA-10046
def test_batch_mutate_remove_slice_standard(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
columns = [Column(utf8encode('c1'), utf8encode('value1'), 0),
Column(utf8encode('c2'), utf8encode('value2'), 0),
Column(utf8encode('c3'), utf8encode('value3'), 0),
Column(utf8encode('c4'), utf8encode('value4'), 0),
Column(utf8encode('c5'), utf8encode('value5'), 0)]
for column in columns:
client.insert(utf8encode('key'), ColumnParent('Standard1'), column, ConsistencyLevel.ONE)
d = Deletion(1, predicate=SlicePredicate(slice_range=SliceRange(start=utf8encode('c2'), finish=utf8encode('c4'))))
client.batch_mutate({utf8encode('key'): {'Standard1': [Mutation(deletion=d)]}}, ConsistencyLevel.ONE)
_assert_columnpath_exists(utf8encode('key'), ColumnPath('Standard1', column=utf8encode('c1')))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Standard1', column=utf8encode('c2')))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Standard1', column=utf8encode('c3')))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Standard1', column=utf8encode('c4')))
_assert_columnpath_exists(utf8encode('key'), ColumnPath('Standard1', column=utf8encode('c5')))
# known failure: see CASSANDRA-10046
def test_batch_mutate_remove_slice_of_entire_supercolumns(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
columns = [SuperColumn(name=utf8encode('sc1'), columns=[Column(_i64(1), utf8encode('value1'), 0)]),
SuperColumn(name=utf8encode('sc2'),
columns=[Column(_i64(2), utf8encode('value2') , 0), Column(_i64(3), utf8encode('value3') , 0)]),
SuperColumn(name=utf8encode('sc3'), columns=[Column(_i64(4), utf8encode('value4'), 0)]),
SuperColumn(name=utf8encode('sc4'),
columns=[Column(_i64(5), utf8encode('value5') , 0), Column(_i64(6), utf8encode('value6') , 0)]),
SuperColumn(name=utf8encode('sc5'), columns=[Column(_i64(7), utf8encode('value7'), 0)])]
for column in columns:
for subcolumn in column.columns:
client.insert(utf8encode('key'), ColumnParent('Super1', column.name), subcolumn, ConsistencyLevel.ONE)
d = Deletion(1, predicate=SlicePredicate(slice_range=SliceRange(start=utf8encode('sc2') , finish=utf8encode('sc4') )))
client.batch_mutate({utf8encode('key'): {'Super1': [Mutation(deletion=d)]}}, ConsistencyLevel.ONE)
_assert_columnpath_exists(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc1'), column=_i64(1)))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc2'), column=_i64(2)))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc2'), column=_i64(3)))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc3'), column=_i64(4)))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc4'), column=_i64(5)))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc4'), column=_i64(6)))
_assert_columnpath_exists(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc5'), column=_i64(7)))
@since('1.0', '2.2')
@pytest.mark.skip(reason="Runs but fails and looks like it actually should fail since 8099?")
def test_batch_mutate_remove_slice_part_of_supercolumns(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
columns = [Column(_i64(1), utf8encode('value1'), 0),
Column(_i64(2), utf8encode('value2'), 0),
Column(_i64(3), utf8encode('value3'), 0),
Column(_i64(4), utf8encode('value4'), 0),
Column(_i64(5), utf8encode('value5'), 0)]
for column in columns:
client.insert(utf8encode('key'), ColumnParent('Super1', utf8encode('sc1')), column, ConsistencyLevel.ONE)
r = SliceRange(start=_i64(2), finish=_i64(4))
d = Deletion(1, super_column=utf8encode('sc1') , predicate=SlicePredicate(slice_range=r))
client.batch_mutate({utf8encode('key'): {'Super1' : [Mutation(deletion=d)]}}, ConsistencyLevel.ONE)
_assert_columnpath_exists(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc1'), column=_i64(1)))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc1'), column=_i64(2)))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc1'), column=_i64(3)))
_assert_no_columnpath(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc1'), column=_i64(4)))
_assert_columnpath_exists(utf8encode('key'), ColumnPath('Super1', super_column=utf8encode('sc1'), column=_i64(5)))
def test_batch_mutate_insertions_and_deletions(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1', 'Super2')
first_insert = SuperColumn(utf8encode("sc1"),
columns=[Column(_i64(20), utf8encode('value20'), 3),
Column(_i64(21), utf8encode('value21'), 3)])
second_insert = SuperColumn(utf8encode("sc1"),
columns=[Column(_i64(20), utf8encode('value20'), 3),
Column(_i64(21), utf8encode('value21'), 3)])
first_deletion = {'super_column': utf8encode("sc1"),
'predicate': SlicePredicate(column_names=[_i64(22), _i64(23)])}
second_deletion = {'super_column': utf8encode("sc2"),
'predicate': SlicePredicate(column_names=[_i64(22), _i64(23)])}
keys = [utf8encode('key_30'), utf8encode('key_31')]
for key in keys:
sc = SuperColumn(utf8encode('sc1'), [Column(_i64(22), utf8encode('value22'), 0),
Column(_i64(23), utf8encode('value23'), 0)])
cfmap = {'Super1': [Mutation(ColumnOrSuperColumn(super_column=sc))]}
client.batch_mutate({key: cfmap}, ConsistencyLevel.ONE)
sc2 = SuperColumn(utf8encode('sc2'), [Column(_i64(22), utf8encode('value22'), 0),
Column(_i64(23), utf8encode('value23'), 0)])
cfmap2 = {'Super2': [Mutation(ColumnOrSuperColumn(super_column=sc2))]}
client.batch_mutate({key: cfmap2}, ConsistencyLevel.ONE)
cfmap3 = {
'Super1': [Mutation(ColumnOrSuperColumn(super_column=first_insert)),
Mutation(deletion=Deletion(3, **first_deletion))],
'Super2': [Mutation(deletion=Deletion(2, **second_deletion)),
Mutation(ColumnOrSuperColumn(super_column=second_insert))]
}
keyed_mutations = dict((key, cfmap3) for key in keys)
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
for key in keys:
for c in [_i64(22), _i64(23)]:
_assert_no_columnpath(key, ColumnPath('Super1', super_column=utf8encode('sc1'), column=c))
_assert_no_columnpath(key, ColumnPath('Super2', super_column=utf8encode('sc2'), column=c))
for c in [_i64(20), _i64(21)]:
_assert_columnpath_exists(key, ColumnPath('Super1', super_column=utf8encode('sc1'), column=c))
_assert_columnpath_exists(key, ColumnPath('Super2', super_column=utf8encode('sc1'), column=c))
def test_bad_system_calls(self):
def duplicate_index_names():
_set_keyspace('Keyspace1')
cd1 = ColumnDef(utf8encode('foo'), 'BytesType', IndexType.KEYS, 'i')
cd2 = ColumnDef(utf8encode('bar'), 'BytesType', IndexType.KEYS, 'i')
cf = CfDef('Keyspace1', 'BadCF', column_metadata=[cd1, cd2])
client.system_add_column_family(cf)
_expect_exception(duplicate_index_names, InvalidRequestException)
def test_bad_batch_calls(self):
# mutate_does_not_accept_cosc_and_deletion_in_same_mutation
def too_full():
_set_keyspace('Keyspace1')
col = ColumnOrSuperColumn(column=Column(utf8encode("foo"), utf8encode('bar'), 0))
dele = Deletion(2, predicate=SlicePredicate(column_names=[utf8encode('baz')]))
client.batch_mutate({utf8encode('key_34'): {'Standard1': [Mutation(col, dele)]}},
ConsistencyLevel.ONE)
_expect_exception(too_full, InvalidRequestException)
# test_batch_mutate_does_not_accept_cosc_on_undefined_cf:
def bad_cf():
_set_keyspace('Keyspace1')
col = ColumnOrSuperColumn(column=Column(utf8encode("foo"), utf8encode('bar'), 0))
client.batch_mutate({utf8encode('key_36'): {'Undefined': [Mutation(col)]}},
ConsistencyLevel.ONE)
_expect_exception(bad_cf, InvalidRequestException)
# test_batch_mutate_does_not_accept_deletion_on_undefined_cf
def bad_cf_2():
_set_keyspace('Keyspace1')
d = Deletion(2, predicate=SlicePredicate(column_names=[utf8encode('baz')]))
client.batch_mutate({utf8encode('key_37'): {'Undefined': [Mutation(deletion=d)]}},
ConsistencyLevel.ONE)
_expect_exception(bad_cf_2, InvalidRequestException)
# a column value that does not match the declared validator
def send_string_instead_of_long():
_set_keyspace('Keyspace1')
col = ColumnOrSuperColumn(column=Column(utf8encode('birthdate'), utf8encode('bar'), 0))
client.batch_mutate({utf8encode('key_38'): {'Indexed1': [Mutation(col)]}},
ConsistencyLevel.ONE)
_expect_exception(send_string_instead_of_long, InvalidRequestException)
def test_column_name_lengths(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
_expect_exception(lambda: client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode(''), utf8encode('value'), 0), ConsistencyLevel.ONE), InvalidRequestException)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('x' * 1), utf8encode('value'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('x' * 127), utf8encode('value'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('x' * 128), utf8encode('value'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('x' * 129), utf8encode('value'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('x' * 255), utf8encode('value'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('x' * 256), utf8encode('value'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('x' * 257), utf8encode('value'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('x' * (2 ** 16 - 1)), utf8encode('value'), 0), ConsistencyLevel.ONE)
_expect_exception(lambda: client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('x' * (2 ** 16)), utf8encode('value'), 0), ConsistencyLevel.ONE), InvalidRequestException)
def test_bad_calls(self):
_set_keyspace('Keyspace1')
# missing arguments
_expect_exception(lambda: client.insert(None, None, None, None), TApplicationException)
# supercolumn in a non-super CF
_expect_exception(lambda: client.insert(utf8encode('key1'), ColumnParent('Standard1', utf8encode('x')), Column(utf8encode('y'), utf8encode('value'), 0), ConsistencyLevel.ONE), InvalidRequestException)
# no supercolumn in a super CF
_expect_exception(lambda: client.insert(utf8encode('key1'), ColumnParent('Super1'), Column(utf8encode('y'), utf8encode('value'), 0), ConsistencyLevel.ONE), InvalidRequestException)
# column but no supercolumn in remove
_expect_exception(lambda: client.remove(utf8encode('key1'), ColumnPath('Super1', column=utf8encode('x')), 0, ConsistencyLevel.ONE), InvalidRequestException)
# super column in non-super CF
_expect_exception(lambda: client.remove(utf8encode('key1'), ColumnPath('Standard1', utf8encode('y'), utf8encode('x')), 0, ConsistencyLevel.ONE), InvalidRequestException)
# key too long
_expect_exception(lambda: client.get(utf8encode('x' * 2 ** 16), ColumnPath('Standard1', column=utf8encode('c1')), ConsistencyLevel.ONE), InvalidRequestException)
# empty key
_expect_exception(lambda: client.get(utf8encode(''), ColumnPath('Standard1', column=utf8encode('c1')), ConsistencyLevel.ONE), InvalidRequestException)
cfmap = {'Super1': [Mutation(ColumnOrSuperColumn(super_column=c)) for c in _SUPER_COLUMNS],
'Super2': [Mutation(ColumnOrSuperColumn(super_column=c)) for c in _SUPER_COLUMNS]}
_expect_exception(lambda: client.batch_mutate({utf8encode(''): cfmap}, ConsistencyLevel.ONE), InvalidRequestException)
# empty column name
_expect_exception(lambda: client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('')), ConsistencyLevel.ONE), InvalidRequestException)
# get doesn't specify column name
_expect_exception(lambda: client.get(utf8encode('key1'), ColumnPath('Standard1'), ConsistencyLevel.ONE), InvalidRequestException)
# supercolumn in a non-super CF
_expect_exception(lambda: client.get(utf8encode('key1'), ColumnPath('Standard1', utf8encode('x'), utf8encode('y')), ConsistencyLevel.ONE), InvalidRequestException)
# get doesn't specify supercolumn name
_expect_exception(lambda: client.get(utf8encode('key1'), ColumnPath('Super1'), ConsistencyLevel.ONE), InvalidRequestException)
# invalid CF
_expect_exception(lambda: get_range_slice(client, ColumnParent('S'), SlicePredicate(column_names=[utf8encode(''), utf8encode('')]), utf8encode(''), utf8encode(''), 5, ConsistencyLevel.ONE), InvalidRequestException)
# 'x' is not a valid Long
_expect_exception(lambda: client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc1')), Column(utf8encode('x'), utf8encode('value'), 0), ConsistencyLevel.ONE), InvalidRequestException)
# start is not a valid Long
p = SlicePredicate(slice_range=SliceRange(utf8encode('x'), utf8encode(''), False, 1))
column_parent = ColumnParent('StandardLong1')
_expect_exception(lambda: client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE),
InvalidRequestException)
# start > finish
p = SlicePredicate(slice_range=SliceRange(_i64(10), _i64(0), False, 1))
column_parent = ColumnParent('StandardLong1')
_expect_exception(lambda: client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE),
InvalidRequestException)
# start is not a valid Long, supercolumn version
p = SlicePredicate(slice_range=SliceRange(utf8encode('x'), utf8encode(''), False, 1))
column_parent = ColumnParent('Super1', utf8encode('sc1'))
_expect_exception(lambda: client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE),
InvalidRequestException)
# start > finish, supercolumn version
p = SlicePredicate(slice_range=SliceRange(_i64(10), _i64(0), False, 1))
column_parent = ColumnParent('Super1', utf8encode('sc1'))
_expect_exception(lambda: client.get_slice(utf8encode('key1'), column_parent, p, ConsistencyLevel.ONE),
InvalidRequestException)
# start > finish, key version
_expect_exception(lambda: get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('')]), utf8encode('z'), utf8encode('a'), 1, ConsistencyLevel.ONE), InvalidRequestException)
# ttl must be greater or equals to zero
column = Column(utf8encode('cttl1'), utf8encode('value1'), 0, -1)
_expect_exception(lambda: client.insert(utf8encode('key1'), ColumnParent('Standard1'), column, ConsistencyLevel.ONE),
InvalidRequestException)
# don't allow super_column in Deletion for standard Columntest_expiration_with_default_ttl_and_zero_ttl
deletion = Deletion(1, utf8encode('supercolumn'), None)
mutation = Mutation(deletion=deletion)
mutations = {utf8encode('key'): {'Standard1': [mutation]}}
_expect_exception(lambda: client.batch_mutate(mutations, ConsistencyLevel.QUORUM),
InvalidRequestException)
# 'x' is not a valid long
deletion = Deletion(1, utf8encode('x'), None)
mutation = Mutation(deletion=deletion)
mutations = {utf8encode('key'): {'Super3': [mutation]}}
_expect_exception(lambda: client.batch_mutate(mutations, ConsistencyLevel.QUORUM), InvalidRequestException)
# counters don't support ANY
_expect_exception(lambda: client.add(utf8encode('key1'), ColumnParent('Counter1', utf8encode('x')), CounterColumn(utf8encode('y'), 1), ConsistencyLevel.ANY), InvalidRequestException)
def test_batch_insert_super(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1', 'Super2')
cfmap = {'Super1': [Mutation(ColumnOrSuperColumn(super_column=c))
for c in _SUPER_COLUMNS],
'Super2': [Mutation(ColumnOrSuperColumn(super_column=c))
for c in _SUPER_COLUMNS]}
client.batch_mutate({utf8encode('key1'): cfmap}, ConsistencyLevel.ONE)
_verify_super('Super1')
_verify_super('Super2')
def test_cf_remove_column(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
_insert_simple()
client.remove(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('c1')), 1, ConsistencyLevel.ONE)
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('c1')), ConsistencyLevel.ONE))
assert client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('c2')), ConsistencyLevel.ONE).column \
== Column(utf8encode('c2'), utf8encode('value2'), 0)
assert _big_slice(utf8encode('key1'), ColumnParent('Standard1')) \
== [ColumnOrSuperColumn(column=Column(utf8encode('c2'), utf8encode('value2'), 0))]
# New insert, make sure it shows up post-remove:
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c3'), utf8encode('value3'), 0), ConsistencyLevel.ONE)
columns = [result.column
for result in _big_slice(utf8encode('key1'), ColumnParent('Standard1'))]
assert columns == [Column(utf8encode('c2'), utf8encode('value2'), 0), Column(utf8encode('c3'), utf8encode('value3'), 0)], columns
# Test resurrection. First, re-insert the value w/ older timestamp,
# and make sure it stays removed
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c1'), utf8encode('value1'), 0), ConsistencyLevel.ONE)
columns = [result.column
for result in _big_slice(utf8encode('key1'), ColumnParent('Standard1'))]
assert columns == [Column(utf8encode('c2'), utf8encode('value2'), 0), Column(utf8encode('c3'), utf8encode('value3'), 0)], columns
# Next, w/ a newer timestamp; it should come back:
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c1'), utf8encode('value1'), 2), ConsistencyLevel.ONE)
columns = [result.column
for result in _big_slice(utf8encode('key1'), ColumnParent('Standard1'))]
assert columns == [Column(utf8encode('c1'), utf8encode('value1'), 2), Column(utf8encode('c2'), utf8encode('value2'), 0), Column(utf8encode('c3'), utf8encode('value3'), 0)], columns
def test_cf_remove(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Super1')
_insert_simple()
_insert_super()
# Remove the key1:Standard1 cf; verify super is unaffected
client.remove(utf8encode('key1'), ColumnPath('Standard1'), 3, ConsistencyLevel.ONE)
assert _big_slice(utf8encode('key1'), ColumnParent('Standard1')) == []
_verify_super()
# Test resurrection. First, re-insert a value w/ older timestamp,
# and make sure it stays removed:
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c1'), utf8encode('value1'), 0), ConsistencyLevel.ONE)
assert _big_slice(utf8encode('key1'), ColumnParent('Standard1')) == []
# Next, w/ a newer timestamp; it should come back:
client.insert(utf8encode('key1'), ColumnParent('Standard1'), Column(utf8encode('c1'), utf8encode('value1'), 4), ConsistencyLevel.ONE)
result = _big_slice(utf8encode('key1'), ColumnParent('Standard1'))
assert result == [ColumnOrSuperColumn(column=Column(utf8encode('c1'), utf8encode('value1'), 4))], result
# check removing the entire super cf, too.
client.remove(utf8encode('key1'), ColumnPath('Super1'), 3, ConsistencyLevel.ONE)
assert _big_slice(utf8encode('key1'), ColumnParent('Super1')) == []
assert _big_slice(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc1'))) == []
def test_super_cf_remove_and_range_slice(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
client.insert(utf8encode('key3'), ColumnParent('Super1', utf8encode('sc1')), Column(_i64(1), utf8encode('v1'), 0), ConsistencyLevel.ONE)
client.remove(utf8encode('key3'), ColumnPath('Super1', utf8encode('sc1')), 5, ConsistencyLevel.ONE)
rows = {}
for row in get_range_slice(client, ColumnParent('Super1'), SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1000)), utf8encode(''), utf8encode(''), 1000, ConsistencyLevel.ONE):
scs = [cosc.super_column for cosc in row.columns]
rows[row.key] = scs
assert rows == {utf8encode('key3'): []}, rows
def test_super_cf_remove_column(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Super1')
_insert_simple()
_insert_super()
# Make sure remove clears out what it's supposed to, and _only_ that:
client.remove(utf8encode('key1'), ColumnPath('Super1', utf8encode('sc2'), _i64(5)), 5, ConsistencyLevel.ONE)
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Super1', utf8encode('sc2'), _i64(5)), ConsistencyLevel.ONE))
super_columns = [result.super_column for result in _big_slice(utf8encode('key1'), ColumnParent('Super1'))]
assert super_columns == [SuperColumn(name=utf8encode('sc1'), columns=[Column(_i64(4), utf8encode('value4'), 0)]),
SuperColumn(name=utf8encode('sc2'), columns=[Column(_i64(6), utf8encode('value6'), 0)])]
_verify_simple()
# New insert, make sure it shows up post-remove:
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), Column(_i64(7), utf8encode('value7'), 0), ConsistencyLevel.ONE)
super_columns_expected = [SuperColumn(name=utf8encode('sc1'),
columns=[Column(_i64(4), utf8encode('value4'), 0)]),
SuperColumn(name=utf8encode('sc2'),
columns=[Column(_i64(6), utf8encode('value6'), 0), Column(_i64(7), utf8encode('value7'), 0)])]
super_columns = [result.super_column for result in _big_slice(utf8encode('key1'), ColumnParent('Super1'))]
assert super_columns == super_columns_expected, super_columns
# Test resurrection. First, re-insert the value w/ older timestamp,
# and make sure it stays removed:
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), Column(_i64(5), utf8encode('value5'), 0), ConsistencyLevel.ONE)
super_columns = [result.super_column for result in _big_slice(utf8encode('key1'), ColumnParent('Super1'))]
assert super_columns == super_columns_expected, super_columns
# Next, w/ a newer timestamp; it should come back
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), Column(_i64(5), utf8encode('value5'), 6), ConsistencyLevel.ONE)
super_columns = [result.super_column for result in _big_slice(utf8encode('key1'), ColumnParent('Super1'))]
super_columns_expected = [SuperColumn(name=utf8encode('sc1'), columns=[Column(_i64(4), utf8encode('value4'), 0)]),
SuperColumn(name=utf8encode('sc2'), columns=[Column(_i64(5), utf8encode('value5'), 6),
Column(_i64(6), utf8encode('value6'), 0),
Column(_i64(7), utf8encode('value7'), 0)])]
assert super_columns == super_columns_expected, super_columns
# shouldn't be able to specify a column w/o a super column for remove
cp = ColumnPath(column_family='Super1', column=utf8encode('sc2'))
e = _expect_exception(lambda: client.remove(utf8encode('key1'), cp, 5, ConsistencyLevel.ONE), InvalidRequestException)
assert e.why.find("column cannot be specified without") >= 0
def test_super_cf_remove_supercolumn(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Super1')
_insert_simple()
_insert_super()
# Make sure remove clears out what it's supposed to, and _only_ that:
client.remove(utf8encode('key1'), ColumnPath('Super1', utf8encode('sc2')), 5, ConsistencyLevel.ONE)
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Super1', utf8encode('sc2'), _i64(5)), ConsistencyLevel.ONE))
super_columns = _big_slice(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')))
assert super_columns == [], super_columns
super_columns_expected = [SuperColumn(name=utf8encode('sc1'), columns=[Column(_i64(4), utf8encode('value4'), 0)])]
super_columns = [result.super_column
for result in _big_slice(utf8encode('key1'), ColumnParent('Super1'))]
assert super_columns == super_columns_expected, super_columns
_verify_simple()
# Test resurrection. First, re-insert the value w/ older timestamp,
# and make sure it stays removed:
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), Column(_i64(5), utf8encode('value5'), 1), ConsistencyLevel.ONE)
super_columns = [result.super_column
for result in _big_slice(utf8encode('key1'), ColumnParent('Super1'))]
assert super_columns == super_columns_expected, super_columns
# Next, w/ a newer timestamp; it should come back
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), Column(_i64(5), utf8encode('value5'), 6), ConsistencyLevel.ONE)
super_columns = [result.super_column
for result in _big_slice(utf8encode('key1'), ColumnParent('Super1'))]
super_columns_expected = [SuperColumn(name=utf8encode('sc1'), columns=[Column(_i64(4), utf8encode('value4'), 0)]),
SuperColumn(name=utf8encode('sc2'), columns=[Column(_i64(5), utf8encode('value5'), 6)])]
assert super_columns == super_columns_expected, super_columns
# check slicing at the subcolumn level too
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1000))
columns = [result.column
for result in client.get_slice(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), p, ConsistencyLevel.ONE)]
assert columns == [Column(_i64(5), utf8encode('value5'), 6)], columns
def test_super_cf_resurrect_subcolumn(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
key = utf8encode('vijay')
client.insert(key, ColumnParent('Super1', utf8encode('sc1')), Column(_i64(4), utf8encode('value4'), 0), ConsistencyLevel.ONE)
client.remove(key, ColumnPath('Super1', utf8encode('sc1')), 1, ConsistencyLevel.ONE)
client.insert(key, ColumnParent('Super1', utf8encode('sc1')), Column(_i64(4), utf8encode('value4'), 2), ConsistencyLevel.ONE)
result = client.get(key, ColumnPath('Super1', utf8encode('sc1')), ConsistencyLevel.ONE)
assert result.super_column.columns is not None, result.super_column
def test_empty_range(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Super1')
assert get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('c1'), utf8encode('c1')]), utf8encode(''), utf8encode(''), 1000, ConsistencyLevel.ONE) == []
_insert_simple()
assert get_range_slice(client, ColumnParent('Super1'), SlicePredicate(column_names=[utf8encode('c1'), utf8encode('c1')]), utf8encode(''), utf8encode(''), 1000, ConsistencyLevel.ONE) == []
@since('2.1', max_version='4')
def test_super_cql_read_compatibility(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
_insert_super(utf8encode("key1"))
_insert_super(utf8encode("key2"))
node1 = self.cluster.nodelist()[0]
session = self.patient_cql_connection(node1)
session.execute('USE "Keyspace1"')
assert_all(session, "SELECT * FROM \"Super1\"",
[[utf8encode("key1"), utf8encode("sc1"), 4, utf8encode("value4")],
[utf8encode("key1"), utf8encode("sc2"), 5, utf8encode("value5")],
[utf8encode("key1"), utf8encode("sc2"), 6, utf8encode("value6")],
[utf8encode("key2"), utf8encode("sc1"), 4, utf8encode("value4")],
[utf8encode("key2"), utf8encode("sc2"), 5, utf8encode("value5")],
[utf8encode("key2"), utf8encode("sc2"), 6, utf8encode("value6")]])
assert_all(session, "SELECT * FROM \"Super1\" WHERE key=textAsBlob('key1')",
[[utf8encode("key1"), utf8encode("sc1"), 4, utf8encode("value4")],
[utf8encode("key1"), utf8encode("sc2"), 5, utf8encode("value5")],
[utf8encode("key1"), utf8encode("sc2"), 6, utf8encode("value6")]])
assert_all(session, "SELECT * FROM \"Super1\" WHERE key=textAsBlob('key1') AND column1=textAsBlob('sc2')",
[[utf8encode("key1"), utf8encode("sc2"), 5, utf8encode("value5")],
[utf8encode("key1"), utf8encode("sc2"), 6, utf8encode("value6")]])
assert_all(session, "SELECT * FROM \"Super1\" WHERE key=textAsBlob('key1') AND column1=textAsBlob('sc2') AND column2 = 5",
[[utf8encode("key1"), utf8encode("sc2"), 5, utf8encode("value5")]])
assert_all(session, "SELECT * FROM \"Super1\" WHERE key = textAsBlob('key1') AND column1 = textAsBlob('sc2')",
[[utf8encode("key1"), utf8encode("sc2"), 5, utf8encode("value5")],
[utf8encode("key1"), utf8encode("sc2"), 6, utf8encode("value6")]])
assert_all(session, "SELECT column2, value FROM \"Super1\" WHERE key = textAsBlob('key1') AND column1 = textAsBlob('sc2')",
[[5, utf8encode("value5")],
[6, utf8encode("value6")]])
@since('2.1', max_version='4')
def test_super_cql_write_compatibility(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
node1 = self.cluster.nodelist()[0]
session = self.patient_cql_connection(node1)
session.execute('USE "Keyspace1"')
query = "INSERT INTO \"Super1\" (key, column1, column2, value) VALUES (textAsBlob(%s), textAsBlob(%s), %s, textAsBlob(%s)) USING TIMESTAMP 1234"
session.execute(query, ("key1", "sc1", 4, "value4"))
session.execute(query, ("key1", "sc2", 5, "value5"))
session.execute(query, ("key1", "sc2", 6, "value6"))
session.execute(query, ("key2", "sc1", 4, "value4"))
session.execute(query, ("key2", "sc2", 5, "value5"))
session.execute(query, ("key2", "sc2", 6, "value6"))
p = SlicePredicate(slice_range=SliceRange(utf8encode('sc1'), utf8encode('sc2'), False, 2))
result = client.get_slice(utf8encode('key1'), ColumnParent('Super1'), p, ConsistencyLevel.ONE)
assert_length_equal(result, 2)
assert result[0].super_column.name == utf8encode('sc1')
assert result[0].super_column.columns[0], Column(_i64(4), utf8encode('value4') == 1234)
assert result[1].super_column.name == utf8encode('sc2')
assert result[1].super_column.columns, [Column(_i64(5), utf8encode('value5'), 1234), Column(_i64(6), utf8encode('value6') == 1234)]
def test_range_with_remove(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
_insert_simple()
assert get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('c1'), utf8encode('c1')]), utf8encode('key1'), utf8encode(''), 1000, ConsistencyLevel.ONE)[0].key == utf8encode('key1')
client.remove(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('c1')), 1, ConsistencyLevel.ONE)
client.remove(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('c2')), 1, ConsistencyLevel.ONE)
actual = get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('c1'), utf8encode('c2')]), utf8encode(''), utf8encode(''), 1000, ConsistencyLevel.ONE)
assert actual == [KeySlice(columns=[], key=utf8encode('key1'))], actual
def test_range_with_remove_cf(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
_insert_simple()
assert get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('c1'), utf8encode('c1')]), utf8encode('key1'), utf8encode(''), 1000, ConsistencyLevel.ONE)[0].key == utf8encode('key1')
client.remove(utf8encode('key1'), ColumnPath('Standard1'), 1, ConsistencyLevel.ONE)
actual = get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('c1'), utf8encode('c1')]), utf8encode(''), utf8encode(''), 1000, ConsistencyLevel.ONE)
assert actual == [KeySlice(columns=[], key=utf8encode('key1'))], actual
def test_range_collation(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
for key in ['-a', '-b', 'a', 'b'] + [str(i) for i in range(100)]:
key = utf8encode(key)
client.insert(key, ColumnParent('Standard1'), Column(key, utf8encode('v'), 0), ConsistencyLevel.ONE)
slices = get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('-a'), utf8encode('-a')]), utf8encode(''), utf8encode(''), 1000, ConsistencyLevel.ONE)
L = ['-a', '-b', '0', '1', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '2', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '3', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '4', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '5', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '6', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '7', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '8', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '9', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', 'a', 'b']
assert len(slices) == len(L)
for key, ks in zip(L, slices):
key = utf8encode(key)
assert key == ks.key
def test_range_partial(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
for key in ['-a', '-b', 'a', 'b'] + [str(i) for i in range(100)]:
key = utf8encode(key)
client.insert(key, ColumnParent('Standard1'), Column(key, utf8encode('v'), 0), ConsistencyLevel.ONE)
def check_slices_against_keys(keyList, sliceList):
assert len(keyList) == len(sliceList), "%d vs %d" % (len(keyList), len(sliceList))
for key, ks in zip(keyList, sliceList):
key = utf8encode(key)
assert key == ks.key
slices = get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('-a'), utf8encode('-a')]), utf8encode('a'), utf8encode(''), 1000, ConsistencyLevel.ONE)
check_slices_against_keys(['a', 'b'], slices)
slices = get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('-a'), utf8encode('-a')]), utf8encode(''), utf8encode('15'), 1000, ConsistencyLevel.ONE)
check_slices_against_keys(['-a', '-b', '0', '1', '10', '11', '12', '13', '14', '15'], slices)
slices = get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('-a'), utf8encode('-a')]), utf8encode('50'), utf8encode('51'), 1000, ConsistencyLevel.ONE)
check_slices_against_keys(['50', '51'], slices)
slices = get_range_slice(client, ColumnParent('Standard1'), SlicePredicate(column_names=[utf8encode('-a'), utf8encode('-a')]), utf8encode('1'), utf8encode(''), 10, ConsistencyLevel.ONE)
check_slices_against_keys(['1', '10', '11', '12', '13', '14', '15', '16', '17', '18'], slices)
def test_get_slice_range(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
_insert_range()
_verify_range()
def test_get_slice_super_range(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
_insert_super_range()
_verify_super_range()
def test_get_range_slices_tokens(self):
_set_keyspace('Keyspace2')
self.truncate_all('Super3')
for key in ['key1', 'key2', 'key3', 'key4', 'key5']:
key = utf8encode(key)
for cname in ['col1', 'col2', 'col3', 'col4', 'col5']:
cnameutf = utf8encode(cname)
client.insert(key, ColumnParent('Super3', utf8encode('sc1')), Column(cnameutf, utf8encode('v-' + cname), 0), ConsistencyLevel.ONE)
cp = ColumnParent('Super3', utf8encode('sc1'))
predicate = SlicePredicate(column_names=[utf8encode('col1'), utf8encode('col3')])
range = KeyRange(start_token='55', end_token='55', count=100)
result = client.get_range_slices(cp, predicate, range, ConsistencyLevel.ONE)
assert len(result) == 5
assert result[0].columns[0].column.name == utf8encode('col1')
assert result[0].columns[1].column.name == utf8encode('col3')
def test_get_range_slice_super(self):
_set_keyspace('Keyspace2')
self.truncate_all('Super3')
for key in ['key1', 'key2', 'key3', 'key4', 'key5']:
key = utf8encode(key)
for cname in ['col1', 'col2', 'col3', 'col4', 'col5']:
cnameutf = utf8encode(cname)
client.insert(key, ColumnParent('Super3', utf8encode('sc1')), Column(cnameutf, utf8encode('v-' + cname), 0), ConsistencyLevel.ONE)
cp = ColumnParent('Super3', utf8encode('sc1'))
result = get_range_slice(client, cp, SlicePredicate(column_names=[utf8encode('col1'), utf8encode('col3')]), utf8encode('key2'), utf8encode('key4'), 5, ConsistencyLevel.ONE)
assert len(result) == 3
assert result[0].columns[0].column.name == utf8encode('col1')
assert result[0].columns[1].column.name == utf8encode('col3')
cp = ColumnParent('Super3')
result = get_range_slice(client, cp, SlicePredicate(column_names=[utf8encode('sc1')]), utf8encode('key2'), utf8encode('key4'), 5, ConsistencyLevel.ONE)
assert len(result) == 3
assert list(set(row.columns[0].super_column.name for row in result))[0] == utf8encode('sc1')
def test_get_range_slice(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
for key in ['key1', 'key2', 'key3', 'key4', 'key5']:
key = utf8encode(key)
for cname in ['col1', 'col2', 'col3', 'col4', 'col5']:
cnameutf = utf8encode(cname)
client.insert(key, ColumnParent('Standard1'), Column(cnameutf, utf8encode('v-' + cname), 0), ConsistencyLevel.ONE)
cp = ColumnParent('Standard1')
# test empty slice
result = get_range_slice(client, cp, SlicePredicate(column_names=[utf8encode('col1'), utf8encode('col3')]), utf8encode('key6'), utf8encode(''), 1, ConsistencyLevel.ONE)
assert len(result) == 0
# test empty columns
result = get_range_slice(client, cp, SlicePredicate(column_names=[utf8encode('a')]), utf8encode('key2'), utf8encode(''), 1, ConsistencyLevel.ONE)
assert len(result) == 1
assert len(result[0].columns) == 0
# test column_names predicate
result = get_range_slice(client, cp, SlicePredicate(column_names=[utf8encode('col1'), utf8encode('col3')]), utf8encode('key2'), utf8encode('key4'), 5, ConsistencyLevel.ONE)
assert len(result) == 3, result
assert result[0].columns[0].column.name == utf8encode('col1')
assert result[0].columns[1].column.name == utf8encode('col3')
# row limiting via count.
result = get_range_slice(client, cp, SlicePredicate(column_names=[utf8encode('col1'), utf8encode('col3')]), utf8encode('key2'), utf8encode('key4'), 1, ConsistencyLevel.ONE)
assert len(result) == 1
# test column slice predicate
result = get_range_slice(client, cp, SlicePredicate(slice_range=SliceRange(start=utf8encode('col2'), finish=utf8encode('col4'), reversed=False, count=5)), utf8encode('key1'), utf8encode('key2'), 5, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].key == utf8encode('key1')
assert result[1].key == utf8encode('key2')
assert len(result[0].columns) == 3
assert result[0].columns[0].column.name == utf8encode('col2')
assert result[0].columns[2].column.name == utf8encode('col4')
# col limiting via count
result = get_range_slice(client, cp, SlicePredicate(slice_range=SliceRange(start=utf8encode('col2'), finish=utf8encode('col4'), reversed=False, count=2)), utf8encode('key1'), utf8encode('key2'), 5, ConsistencyLevel.ONE)
assert len(result[0].columns) == 2
# and reversed
result = get_range_slice(client, cp, SlicePredicate(slice_range=SliceRange(start=utf8encode('col4'), finish=utf8encode('col2'), reversed=True, count=5)), utf8encode('key1'), utf8encode('key2'), 5, ConsistencyLevel.ONE)
assert result[0].columns[0].column.name == utf8encode('col4')
assert result[0].columns[2].column.name == utf8encode('col2')
# row limiting via count
result = get_range_slice(client, cp, SlicePredicate(slice_range=SliceRange(start=utf8encode('col2'), finish=utf8encode('col4'), reversed=False, count=5)), utf8encode('key1'), utf8encode('key2'), 1, ConsistencyLevel.ONE)
assert len(result) == 1
# removed data
client.remove(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('col1')), 1, ConsistencyLevel.ONE)
result = get_range_slice(client, cp, SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''))), utf8encode('key1'), utf8encode('key2'), 5, ConsistencyLevel.ONE)
assert len(result) == 2, result
assert result[0].columns[0].column.name == utf8encode('col2'), result[0].columns[0].column.name
assert result[1].columns[0].column.name == utf8encode('col1')
def test_wrapped_range_slices(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
def copp_token(key):
# I cheated and generated this from Java
return {'a': '00530000000100000001',
'b': '00540000000100000001',
'c': '00550000000100000001',
'd': '00560000000100000001',
'e': '00580000000100000001'}[key]
keylist = [utf8encode(key) for key in ['a', 'b', 'c', 'd', 'e']]
for key in keylist:
for cname in ['col1', 'col2', 'col3', 'col4', 'col5']:
cnameutf = utf8encode(cname)
client.insert(key, ColumnParent('Standard1'), Column(cnameutf, utf8encode('v-' + cname), 0), ConsistencyLevel.ONE)
cp = ColumnParent('Standard1')
result = client.get_range_slices(cp, SlicePredicate(column_names=[utf8encode('col1'), utf8encode('col3')]), KeyRange(start_token=copp_token('e'), end_token=copp_token('e')), ConsistencyLevel.ONE)
assert [row.key for row in result] == keylist, [row.key for row in result]
result = client.get_range_slices(cp, SlicePredicate(column_names=[utf8encode('col1'), utf8encode('col3')]), KeyRange(start_token=copp_token('c'), end_token=copp_token('c')), ConsistencyLevel.ONE)
assert [row.key for row in result] == keylist, [row.key for row in result]
def test_get_slice_by_names(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1', 'Super1')
_insert_range()
p = SlicePredicate(column_names=[utf8encode('c1'), utf8encode('c2')])
result = client.get_slice(utf8encode('key1'), ColumnParent('Standard1'), p, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].column.name == utf8encode('c1')
assert result[1].column.name == utf8encode('c2')
_insert_super()
p = SlicePredicate(column_names=[_i64(4)])
result = client.get_slice(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc1')), p, ConsistencyLevel.ONE)
assert len(result) == 1
assert result[0].column.name == _i64(4)
def test_multiget_slice_with_compact_table(self):
"""Insert multiple keys in a compact table and retrieve them using the multiget_slice interface"""
_set_keyspace('Keyspace1')
# create
cd = ColumnDef(utf8encode('v'), 'AsciiType', None, None)
newcf = CfDef('Keyspace1', 'CompactColumnFamily', default_validation_class='AsciiType', column_metadata=[cd])
client.system_add_column_family(newcf)
CL = ConsistencyLevel.ONE
for i in range(0, 5):
client.insert(utf8encode('key' + str(i)), ColumnParent('CompactColumnFamily'), Column(utf8encode('v'), utf8encode('value' + str(i)), 0), CL)
time.sleep(0.1)
p = SlicePredicate(column_names=[utf8encode('v')])
rows = client.multiget_slice([utf8encode('key' + str(i)) for i in range(0, 5)], ColumnParent('CompactColumnFamily'), p, ConsistencyLevel.ONE)
for i in range(0, 5):
key = utf8encode('key' + str(i))
assert key in rows
assert len(rows[key]) == 1
assert rows[key][0].column.name == utf8encode('v')
assert rows[key][0].column.value == utf8encode('value' + str(i))
def test_multiget_slice(self):
"""Insert multiple keys and retrieve them using the multiget_slice interface"""
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
# Generate a list of 10 keys and insert them
num_keys = 10
keys = [utf8encode('key' + str(i)) for i in range(1, num_keys + 1)]
_insert_multi(keys)
# Retrieve all 10 key slices
rows = _big_multislice(keys, ColumnParent('Standard1'))
columns = [ColumnOrSuperColumn(c) for c in _SIMPLE_COLUMNS]
# Validate if the returned rows have the keys requested and if the ColumnOrSuperColumn is what was inserted
for key in keys:
assert key in rows
assert columns == rows[key]
def test_multi_count(self):
"""Insert multiple keys and count them using the multiget interface"""
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
# Generate a list of 10 keys countaining 1 to 10 columns and insert them
num_keys = 10
for i in range(1, num_keys + 1):
key = utf8encode('key' + str(i))
for j in range(1, i + 1):
client.insert(key, ColumnParent('Standard1'), Column(utf8encode('c' + str(j)), utf8encode('value' + str(j)), 0), ConsistencyLevel.ONE)
# Count columns in all 10 keys
keys = [utf8encode('key' + str(i)) for i in range(1, num_keys + 1)]
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1000))
counts = client.multiget_count(keys, ColumnParent('Standard1'), p, ConsistencyLevel.ONE)
# Check the returned counts
for i in range(1, num_keys + 1):
key = utf8encode('key' + str(i))
assert counts[key] == i
def test_batch_mutate_super_deletion(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
_insert_super('test')
d = Deletion(1, predicate=SlicePredicate(column_names=[utf8encode('sc1')]))
cfmap = {'Super1': [Mutation(deletion=d)]}
client.batch_mutate({utf8encode('test'): cfmap}, ConsistencyLevel.ONE)
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Super1', utf8encode('sc1')), ConsistencyLevel.ONE))
def test_super_reinsert(self):
_set_keyspace('Keyspace1')
self.truncate_all('Super1')
for x in range(3):
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), Column(_i64(x), utf8encode('value'), 1), ConsistencyLevel.ONE)
client.remove(utf8encode('key1'), ColumnPath('Super1'), 2, ConsistencyLevel.ONE)
for x in range(3):
client.insert(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), Column(_i64(x + 3), utf8encode('value'), 3), ConsistencyLevel.ONE)
for n in range(1, 4):
p = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, n))
slice = client.get_slice(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc2')), p, ConsistencyLevel.ONE)
assert len(slice) == n, "expected %s results; found %s" % (n, slice)
def test_describe_keyspace(self):
try:
client.system_drop_keyspace("ValidKsForUpdate")
except InvalidRequestException:
pass # The keyspace doesn't exit, because this test was run in isolation.
kspaces = client.describe_keyspaces()
if self.cluster.version() >= '3.0':
assert len(kspaces) == 7, [x.name for x in kspaces] # ['Keyspace2', 'Keyspace1', 'system', 'system_traces', 'system_auth', 'system_distributed', 'system_schema']
elif self.cluster.version() >= '2.2':
assert len(kspaces) == 6, [x.name for x in kspaces] # ['Keyspace2', 'Keyspace1', 'system', 'system_traces', 'system_auth', 'system_distributed']
else:
assert len(kspaces) == 4, [x.name for x in kspaces] # ['Keyspace2', 'Keyspace1', 'system', 'system_traces']
sysks = client.describe_keyspace("system")
assert sysks in kspaces
ks1 = client.describe_keyspace("Keyspace1")
assert ks1.strategy_options['replication_factor'] == '1', ks1.strategy_options
for cf in ks1.cf_defs:
if cf.name == "Standard1":
cf0 = cf
break
assert cf0.comparator_type == "org.apache.cassandra.db.marshal.BytesType"
def test_describe(self):
assert client.describe_cluster_name() == 'test'
def test_describe_ring(self):
assert list(client.describe_ring('Keyspace1'))[0].endpoints == ['127.0.0.1']
def test_describe_token_map(self):
# test/conf/cassandra.yaml specifies org.apache.cassandra.dht.ByteOrderedPartitioner
# which uses BytesToken, so this just tests that the string representation of the token
# matches a regex pattern for BytesToken.toString().
ring = list(client.describe_token_map().items())
if not self.dtest_config.use_vnodes:
assert len(ring) == 1
else:
assert len(ring) == int(self.dtest_config.num_tokens)
token, node = ring[0]
if self.dtest_config.use_vnodes:
assert re.match("[0-9A-Fa-f]{32}", token)
assert node == '127.0.0.1'
def test_describe_partitioner(self):
# Make sure this just reads back the values from the config.
assert client.describe_partitioner() == "org.apache.cassandra.dht.ByteOrderedPartitioner"
def test_describe_snitch(self):
assert client.describe_snitch() == "org.apache.cassandra.locator.SimpleSnitch"
def test_invalid_ks_names(self):
def invalid_keyspace():
client.system_add_keyspace(KsDef('in-valid', 'org.apache.cassandra.locator.SimpleStrategy', {'replication_factor': '1'}, cf_defs=[]))
_expect_exception(invalid_keyspace, InvalidRequestException)
def test_invalid_strategy_class(self):
def add_invalid_keyspace():
client.system_add_keyspace(KsDef('ValidKs', 'InvalidStrategyClass', {}, cf_defs=[]))
exc = _expect_exception(add_invalid_keyspace, InvalidRequestException)
s = str(exc)
assert s.find("InvalidStrategyClass") > -1, s
assert s.find("Unable to find replication strategy") > -1, s
def update_invalid_keyspace():
client.system_add_keyspace(KsDef('ValidKsForUpdate', 'org.apache.cassandra.locator.SimpleStrategy', {'replication_factor': '1'}, cf_defs=[]))
client.system_update_keyspace(KsDef('ValidKsForUpdate', 'InvalidStrategyClass', {}, cf_defs=[]))
exc = _expect_exception(update_invalid_keyspace, InvalidRequestException)
s = str(exc)
assert s.find("InvalidStrategyClass") > -1, s
assert s.find("Unable to find replication strategy") > -1, s
def test_invalid_cf_names(self):
def invalid_cf():
_set_keyspace('Keyspace1')
newcf = CfDef('Keyspace1', 'in-valid')
client.system_add_column_family(newcf)
_expect_exception(invalid_cf, InvalidRequestException)
def invalid_cf_inside_new_ks():
cf = CfDef('ValidKsName_invalid_cf', 'in-valid')
_set_keyspace('system')
client.system_add_keyspace(KsDef('ValidKsName_invalid_cf', 'org.apache.cassandra.locator.SimpleStrategy', {'replication_factor': '1'}, cf_defs=[cf]))
_expect_exception(invalid_cf_inside_new_ks, InvalidRequestException)
def test_system_cf_recreate(self):
"ensures that keyspaces and column familes can be dropped and recreated in short order"
for x in range(2):
keyspace = 'test_cf_recreate'
cf_name = 'recreate_cf'
# create
newcf = CfDef(keyspace, cf_name)
newks = KsDef(keyspace, 'org.apache.cassandra.locator.SimpleStrategy', {'replication_factor': '1'}, cf_defs=[newcf])
client.system_add_keyspace(newks)
_set_keyspace(keyspace)
# insert
client.insert(utf8encode('key0'), ColumnParent(cf_name), Column(utf8encode('colA'), utf8encode('colA-value'), 0), ConsistencyLevel.ONE)
col1 = client.get_slice(utf8encode('key0'), ColumnParent(cf_name), SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 100)), ConsistencyLevel.ONE)[0].column
assert col1.name == utf8encode('colA') and col1.value == utf8encode('colA-value')
# drop
client.system_drop_column_family(cf_name)
# recreate
client.system_add_column_family(newcf)
# query
cosc_list = client.get_slice(utf8encode('key0'), ColumnParent(cf_name), SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 100)), ConsistencyLevel.ONE)
# this was failing prior to CASSANDRA-1477.
assert len(cosc_list) == 0, 'cosc length test failed'
client.system_drop_keyspace(keyspace)
def test_system_keyspace_operations(self):
# create. note large RF, this is OK
keyspace = KsDef('CreateKeyspace',
'org.apache.cassandra.locator.SimpleStrategy',
{'replication_factor': '10'},
cf_defs=[CfDef('CreateKeyspace', 'CreateKsCf')])
client.system_add_keyspace(keyspace)
newks = client.describe_keyspace('CreateKeyspace')
assert 'CreateKsCf' in [x.name for x in newks.cf_defs]
_set_keyspace('CreateKeyspace')
# modify valid
modified_keyspace = KsDef('CreateKeyspace',
'org.apache.cassandra.locator.OldNetworkTopologyStrategy',
{'replication_factor': '1'},
cf_defs=[])
client.system_update_keyspace(modified_keyspace)
modks = client.describe_keyspace('CreateKeyspace')
assert modks.strategy_class == modified_keyspace.strategy_class
assert modks.strategy_options == modified_keyspace.strategy_options
# check strategy options are validated on modify
def modify_invalid_ks():
client.system_update_keyspace(KsDef('CreateKeyspace',
'org.apache.cassandra.locator.SimpleStrategy',
{},
cf_defs=[]))
_expect_exception(modify_invalid_ks, InvalidRequestException)
# drop
client.system_drop_keyspace('CreateKeyspace')
def get_second_ks():
client.describe_keyspace('CreateKeyspace')
_expect_exception(get_second_ks, NotFoundException)
# check strategy options are validated on creation
def create_invalid_ks():
client.system_add_keyspace(KsDef('InvalidKeyspace',
'org.apache.cassandra.locator.SimpleStrategy',
{},
cf_defs=[]))
_expect_exception(create_invalid_ks, InvalidRequestException)
def test_create_then_drop_ks(self):
keyspace = KsDef('AddThenDrop',
strategy_class='org.apache.cassandra.locator.SimpleStrategy',
strategy_options={'replication_factor': '1'},
cf_defs=[])
def test_existence():
client.describe_keyspace(keyspace.name)
_expect_exception(test_existence, NotFoundException)
client.set_keyspace('system')
client.system_add_keyspace(keyspace)
test_existence()
client.system_drop_keyspace(keyspace.name)
def test_column_validators(self):
# columndef validation for regular CF
ks = 'Keyspace1'
_set_keyspace(ks)
cd = ColumnDef(utf8encode('col'), 'LongType', None, None)
cf = CfDef('Keyspace1', 'ValidatorColumnFamily', column_metadata=[cd])
client.system_add_column_family(cf)
ks_def = client.describe_keyspace(ks)
assert 'ValidatorColumnFamily' in [x.name for x in ks_def.cf_defs]
cp = ColumnParent('ValidatorColumnFamily')
col0 = Column(utf8encode('col'), _i64(42), 0)
col1 = Column(utf8encode('col'), utf8encode("ceci n'est pas 64bit"), 0)
client.insert(utf8encode('key0'), cp, col0, ConsistencyLevel.ONE)
e = _expect_exception(lambda: client.insert(utf8encode('key1'), cp, col1, ConsistencyLevel.ONE), InvalidRequestException)
assert e.why.find("failed validation") >= 0
# columndef validation for super CF
scf = CfDef('Keyspace1', 'ValidatorSuperColumnFamily', column_type='Super', column_metadata=[cd])
client.system_add_column_family(scf)
ks_def = client.describe_keyspace(ks)
assert 'ValidatorSuperColumnFamily' in [x.name for x in ks_def.cf_defs]
scp = ColumnParent('ValidatorSuperColumnFamily', utf8encode('sc1'))
client.insert(utf8encode('key0'), scp, col0, ConsistencyLevel.ONE)
e = _expect_exception(lambda: client.insert(utf8encode('key1'), scp, col1, ConsistencyLevel.ONE), InvalidRequestException)
assert e.why.find("failed validation") >= 0
# columndef and cfdef default validation
cf = CfDef('Keyspace1', 'DefaultValidatorColumnFamily', column_metadata=[cd], default_validation_class='UTF8Type')
client.system_add_column_family(cf)
ks_def = client.describe_keyspace(ks)
assert 'DefaultValidatorColumnFamily' in [x.name for x in ks_def.cf_defs]
dcp = ColumnParent('DefaultValidatorColumnFamily')
# inserting a longtype into column 'col' is valid at the columndef level
client.insert(utf8encode('key0'), dcp, col0, ConsistencyLevel.ONE)
# inserting a UTF8type into column 'col' fails at the columndef level
e = _expect_exception(lambda: client.insert(utf8encode('key1'), dcp, col1, ConsistencyLevel.ONE), InvalidRequestException)
assert e.why.find("failed validation") >= 0
# insert a longtype into column 'fcol' should fail at the cfdef level
col2 = Column(utf8encode('fcol'), _i64(4224), 0)
e = _expect_exception(lambda: client.insert(utf8encode('key1'), dcp, col2, ConsistencyLevel.ONE), InvalidRequestException)
assert e.why.find("failed validation") >= 0
# insert a UTF8type into column 'fcol' is valid at the cfdef level
col3 = Column(utf8encode('fcol'), utf8encode("Stringin' it up in the Stringtel Stringifornia"), 0)
client.insert(utf8encode('key0'), dcp, col3, ConsistencyLevel.ONE)
def test_system_column_family_operations(self):
_set_keyspace('Keyspace1')
# create
cd = ColumnDef(utf8encode('ValidationColumn'), 'BytesType', None, None)
newcf = CfDef('Keyspace1', 'NewColumnFamily', column_metadata=[cd])
client.system_add_column_family(newcf)
ks1 = client.describe_keyspace('Keyspace1')
assert 'NewColumnFamily' in [x.name for x in ks1.cf_defs]
cfid = [x.id for x in ks1.cf_defs if x.name == 'NewColumnFamily'][0]
# modify invalid
modified_cf = CfDef('Keyspace1', 'NewColumnFamily', column_metadata=[cd])
modified_cf.id = cfid
def fail_invalid_field():
modified_cf.comparator_type = 'LongType'
client.system_update_column_family(modified_cf)
_expect_exception(fail_invalid_field, InvalidRequestException)
# modify valid
modified_cf.comparator_type = 'BytesType' # revert back to old value.
modified_cf.gc_grace_seconds = 1
client.system_update_column_family(modified_cf)
ks1 = client.describe_keyspace('Keyspace1')
server_cf = [x for x in ks1.cf_defs if x.name == 'NewColumnFamily'][0]
assert server_cf
assert server_cf.gc_grace_seconds == 1
# drop
client.system_drop_column_family('NewColumnFamily')
ks1 = client.describe_keyspace('Keyspace1')
assert 'NewColumnFamily' not in [x.name for x in ks1.cf_defs]
assert 'Standard1' in [x.name for x in ks1.cf_defs]
# Make a LongType CF and add a validator
newcf = CfDef('Keyspace1', 'NewLongColumnFamily', comparator_type='LongType')
client.system_add_column_family(newcf)
three = _i64(3)
cd = ColumnDef(three, 'LongType', None, None)
ks1 = client.describe_keyspace('Keyspace1')
modified_cf = [x for x in ks1.cf_defs if x.name == 'NewLongColumnFamily'][0]
modified_cf.column_metadata = [cd]
client.system_update_column_family(modified_cf)
ks1 = client.describe_keyspace('Keyspace1')
server_cf = [x for x in ks1.cf_defs if x.name == 'NewLongColumnFamily'][0]
assert server_cf.column_metadata[0].name == _i64(3), server_cf.column_metadata
def test_dynamic_indexes_creation_deletion(self):
_set_keyspace('Keyspace1')
cfdef = CfDef('Keyspace1', 'BlankCF')
client.system_add_column_family(cfdef)
ks1 = client.describe_keyspace('Keyspace1')
cfid = [x.id for x in ks1.cf_defs if x.name == 'BlankCF'][0]
modified_cd = ColumnDef(utf8encode('birthdate'), 'BytesType', IndexType.KEYS, None)
modified_cf = CfDef('Keyspace1', 'BlankCF', column_metadata=[modified_cd])
modified_cf.id = cfid
client.system_update_column_family(modified_cf)
# Add a second indexed CF ...
birthdate_coldef = ColumnDef(utf8encode('birthdate'), 'BytesType', IndexType.KEYS, None)
age_coldef = ColumnDef(utf8encode('age'), 'BytesType', IndexType.KEYS, 'age_index')
cfdef = CfDef('Keyspace1', 'BlankCF2', column_metadata=[birthdate_coldef, age_coldef])
client.system_add_column_family(cfdef)
# ... and update it to have a third index
ks1 = client.describe_keyspace('Keyspace1')
cfdef = [x for x in ks1.cf_defs if x.name == 'BlankCF2'][0]
name_coldef = ColumnDef(utf8encode('name'), 'BytesType', IndexType.KEYS, 'name_index')
cfdef.column_metadata.append(name_coldef)
client.system_update_column_family(cfdef)
# Now drop the indexes
ks1 = client.describe_keyspace('Keyspace1')
cfdef = [x for x in ks1.cf_defs if x.name == 'BlankCF2'][0]
birthdate_coldef = ColumnDef(utf8encode('birthdate'), 'BytesType', None, None)
age_coldef = ColumnDef(utf8encode('age'), 'BytesType', None, None)
name_coldef = ColumnDef(utf8encode('name'), 'BytesType', None, None)
cfdef.column_metadata = [birthdate_coldef, age_coldef, name_coldef]
client.system_update_column_family(cfdef)
ks1 = client.describe_keyspace('Keyspace1')
cfdef = [x for x in ks1.cf_defs if x.name == 'BlankCF'][0]
birthdate_coldef = ColumnDef(utf8encode('birthdate'), 'BytesType', None, None)
cfdef.column_metadata = [birthdate_coldef]
client.system_update_column_family(cfdef)
client.system_drop_column_family('BlankCF')
client.system_drop_column_family('BlankCF2')
def test_dynamic_indexes_with_system_update_cf(self):
_set_keyspace('Keyspace1')
cd = ColumnDef(utf8encode('birthdate'), 'BytesType', None, None)
newcf = CfDef('Keyspace1', 'ToBeIndexed', default_validation_class='LongType', column_metadata=[cd])
client.system_add_column_family(newcf)
client.insert(utf8encode('key1'), ColumnParent('ToBeIndexed'), Column(utf8encode('birthdate'), _i64(1), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key2'), ColumnParent('ToBeIndexed'), Column(utf8encode('birthdate'), _i64(2), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key2'), ColumnParent('ToBeIndexed'), Column(utf8encode('b'), _i64(2), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key3'), ColumnParent('ToBeIndexed'), Column(utf8encode('birthdate'), _i64(3), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key3'), ColumnParent('ToBeIndexed'), Column(utf8encode('b'), _i64(3), 0), ConsistencyLevel.ONE)
# First without index
cp = ColumnParent('ToBeIndexed')
sp = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode('')))
key_range = KeyRange(utf8encode(''), utf8encode(''), None, None, [IndexExpression(utf8encode('birthdate'), IndexOperator.EQ, _i64(1))], 100)
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 1, result
assert result[0].key == utf8encode('key1')
assert len(result[0].columns) == 1, result[0].columns
# add an index on 'birthdate'
ks1 = client.describe_keyspace('Keyspace1')
cfid = [x.id for x in ks1.cf_defs if x.name == 'ToBeIndexed'][0]
modified_cd = ColumnDef(utf8encode('birthdate'), 'BytesType', IndexType.KEYS, 'bd_index')
modified_cf = CfDef('Keyspace1', 'ToBeIndexed', column_metadata=[modified_cd])
modified_cf.id = cfid
client.system_update_column_family(modified_cf)
ks1 = client.describe_keyspace('Keyspace1')
server_cf = [x for x in ks1.cf_defs if x.name == 'ToBeIndexed'][0]
assert server_cf
assert server_cf.column_metadata[0].index_type == modified_cd.index_type
assert server_cf.column_metadata[0].index_name == modified_cd.index_name
# sleep a bit to give time for the index to build.
time.sleep(5)
# repeat query on one index expression
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 1, result
assert result[0].key == utf8encode('key1')
assert len(result[0].columns) == 1, result[0].columns
def test_system_super_column_family_operations(self):
_set_keyspace('Keyspace1')
# create
cd = ColumnDef(utf8encode('ValidationColumn'), 'BytesType', None, None)
newcf = CfDef('Keyspace1', 'NewSuperColumnFamily', 'Super', column_metadata=[cd])
client.system_add_column_family(newcf)
ks1 = client.describe_keyspace('Keyspace1')
assert 'NewSuperColumnFamily' in [x.name for x in ks1.cf_defs]
# drop
client.system_drop_column_family('NewSuperColumnFamily')
ks1 = client.describe_keyspace('Keyspace1')
assert 'NewSuperColumnFamily' not in [x.name for x in ks1.cf_defs]
assert 'Standard1' in [x.name for x in ks1.cf_defs]
def test_insert_ttl(self):
self._base_insert_ttl()
def test_insert_max_ttl(self):
self._base_insert_ttl(ttl=MAX_TTL, max_default_ttl=False)
def test_insert_max_default_ttl(self):
self._base_insert_ttl(ttl=None, max_default_ttl=True)
def _base_insert_ttl(self, ttl=5, max_default_ttl=False):
""" Test simple insertion of a column with max ttl """
_set_keyspace('Keyspace1')
cf = 'ExpiringMaxTTL' if max_default_ttl else 'Standard1'
logprefix = 'default ' if max_default_ttl else ''
self.truncate_all(cf)
node1 = self.cluster.nodelist()[0]
mark = node1.mark_log()
column = Column(utf8encode('cttl1'), utf8encode('value1'), 0, ttl)
expected = Column(utf8encode('cttl1'), utf8encode('value1'), 0, MAX_TTL) if max_default_ttl else column
client.insert(utf8encode('key1'), ColumnParent(cf), column, ConsistencyLevel.ONE)
assert client.get(utf8encode('key1'), ColumnPath(cf, column=utf8encode('cttl1')), ConsistencyLevel.ONE).column == expected
if ttl and ttl < MAX_TTL:
assert not node1.grep_log("exceeds maximum supported expiration", from_mark=mark), "Should not print max expiration date exceeded warning"
else:
node1.watch_log_for("Request on table {}.{} with {}ttl of {} seconds exceeds maximum supported expiration"
.format('Keyspace1', cf, logprefix, MAX_TTL), timeout=10)
def test_simple_expiration(self):
""" Test that column ttled do expires """
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
column = Column(utf8encode('cttl3'), utf8encode('value1'), 0, 2)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), column, ConsistencyLevel.ONE)
c = client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('cttl3')), ConsistencyLevel.ONE).column
assert c == column
time.sleep(3)
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('cttl3')), ConsistencyLevel.ONE))
def test_expiration_with_default_ttl(self):
""" Test that column with default ttl do expires """
_set_keyspace('Keyspace1')
self.truncate_all('Expiring')
column = Column(utf8encode('cttl3'), utf8encode('value1'), 0)
client.insert(utf8encode('key1'), ColumnParent('Expiring'), column, ConsistencyLevel.ONE)
client.get(utf8encode('key1'), ColumnPath('Expiring', column=utf8encode('cttl3')), ConsistencyLevel.ONE).column
time.sleep(3)
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Expiring', column=utf8encode('cttl3')), ConsistencyLevel.ONE))
@since('3.6', max_version='4')
def test_expiration_with_default_ttl_and_zero_ttl(self):
"""
Test that we can remove the default ttl by setting the ttl explicitly to zero
CASSANDRA-11207
"""
_set_keyspace('Keyspace1')
self.truncate_all('Expiring')
column = Column(utf8encode('cttl3'), utf8encode('value1'), 0, 0)
client.insert(utf8encode('key1'), ColumnParent('Expiring'), column, ConsistencyLevel.ONE)
c = client.get(utf8encode('key1'), ColumnPath('Expiring', column=utf8encode('cttl3')), ConsistencyLevel.ONE).column
assert Column(utf8encode('cttl3'), utf8encode('value1'), 0) == c
def test_simple_expiration_batch_mutate(self):
""" Test that column ttled do expires using batch_mutate """
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
column = Column(utf8encode('cttl4'), utf8encode('value1'), 0, 2)
cfmap = {'Standard1': [Mutation(ColumnOrSuperColumn(column))]}
client.batch_mutate({utf8encode('key1'): cfmap}, ConsistencyLevel.ONE)
c = client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('cttl4')), ConsistencyLevel.ONE).column
assert c == column
time.sleep(3)
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('cttl4')), ConsistencyLevel.ONE))
def test_update_expiring(self):
""" Test that updating a column with ttl override the ttl """
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
column1 = Column(utf8encode('cttl4'), utf8encode('value1'), 0, 1)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), column1, ConsistencyLevel.ONE)
column2 = Column(utf8encode('cttl4'), utf8encode('value1'), 1)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), column2, ConsistencyLevel.ONE)
time.sleep(1.5)
assert client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('cttl4')), ConsistencyLevel.ONE).column == column2
def test_remove_expiring(self):
""" Test removing a column with ttl """
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
column = Column(utf8encode('cttl5'), utf8encode('value1'), 0, 10)
client.insert(utf8encode('key1'), ColumnParent('Standard1'), column, ConsistencyLevel.ONE)
client.remove(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('cttl5')), 1, ConsistencyLevel.ONE)
_expect_missing(lambda: client.get(utf8encode('key1'), ColumnPath('Standard1', column=utf8encode('ctt5')), ConsistencyLevel.ONE))
def test_describe_ring_on_invalid_keyspace(self):
def req():
client.describe_ring('system')
_expect_exception(req, InvalidRequestException)
def test_incr_decr_standard_add(self, request):
_set_keyspace('Keyspace1')
key = utf8encode(request.node.name)
d1 = 12
d2 = -21
d3 = 35
# insert positive and negative values and check the counts
client.add(key, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
time.sleep(0.1)
rv1 = client.get(key, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv1.counter_column.value == d1
client.add(key, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c1'), d2), ConsistencyLevel.ONE)
time.sleep(0.1)
rv2 = client.get(key, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv2.counter_column.value == (d1 + d2)
client.add(key, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c1'), d3), ConsistencyLevel.ONE)
time.sleep(0.1)
rv3 = client.get(key, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv3.counter_column.value == (d1 + d2 + d3)
def test_incr_decr_super_add(self, request):
_set_keyspace('Keyspace1')
key = utf8encode(request.node.name)
d1 = -234
d2 = 52345
d3 = 3123
client.add(key, ColumnParent(column_family='SuperCounter1', super_column=utf8encode('sc1')), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
client.add(key, ColumnParent(column_family='SuperCounter1', super_column=utf8encode('sc1')), CounterColumn(utf8encode('c2'), d2), ConsistencyLevel.ONE)
rv1 = client.get(key, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1')), ConsistencyLevel.ONE)
assert rv1.counter_super_column.columns[0].value == d1
assert rv1.counter_super_column.columns[1].value == d2
client.add(key, ColumnParent(column_family='SuperCounter1', super_column=utf8encode('sc1')), CounterColumn(utf8encode('c1'), d2), ConsistencyLevel.ONE)
rv2 = client.get(key, ColumnPath('SuperCounter1', utf8encode('sc1'), utf8encode('c1')), ConsistencyLevel.ONE)
assert rv2.counter_column.value == (d1 + d2)
client.add(key, ColumnParent(column_family='SuperCounter1', super_column=utf8encode('sc1')), CounterColumn(utf8encode('c1'), d3), ConsistencyLevel.ONE)
rv3 = client.get(key, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv3.counter_column.value == (d1 + d2 + d3)
def test_incr_standard_remove(self, request):
_set_keyspace('Keyspace1')
key1 = utf8encode(request.node.name + "_1")
key2 = utf8encode(request.node.name + "_2")
d1 = 124
# insert value and check it exists
client.add(key1, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
rv1 = client.get(key1, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv1.counter_column.value == d1
# remove the previous column and check that it is gone
client.remove_counter(key1, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
_assert_no_columnpath(key1, ColumnPath(column_family='Counter1', column=utf8encode('c1')))
# insert again and this time delete the whole row, check that it is gone
client.add(key2, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
rv2 = client.get(key2, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv2.counter_column.value == d1
client.remove_counter(key2, ColumnPath(column_family='Counter1'), ConsistencyLevel.ONE)
_assert_no_columnpath(key2, ColumnPath(column_family='Counter1', column=utf8encode('c1')))
def test_incr_super_remove(self, request):
_set_keyspace('Keyspace1')
key1 = utf8encode(request.node.name + "_1")
key2 = utf8encode(request.node.name + "_2")
d1 = 52345
# insert value and check it exists
client.add(key1, ColumnParent(column_family='SuperCounter1', super_column=utf8encode('sc1')), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
rv1 = client.get(key1, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv1.counter_column.value == d1
# remove the previous column and check that it is gone
client.remove_counter(key1, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')), ConsistencyLevel.ONE)
_assert_no_columnpath(key1, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')))
# insert again and this time delete the whole row, check that it is gone
client.add(key2, ColumnParent(column_family='SuperCounter1', super_column=utf8encode('sc1')), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
rv2 = client.get(key2, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv2.counter_column.value == d1
client.remove_counter(key2, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1')), ConsistencyLevel.ONE)
_assert_no_columnpath(key2, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')))
def test_incr_decr_standard_remove(self, request):
_set_keyspace('Keyspace1')
key1 = utf8encode(request.node.name + "_1")
key2 = utf8encode(request.node.name + "_2")
d1 = 124
# insert value and check it exists
client.add(key1, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
rv1 = client.get(key1, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv1.counter_column.value == d1
# remove the previous column and check that it is gone
client.remove_counter(key1, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
_assert_no_columnpath(key1, ColumnPath(column_family='Counter1', column=utf8encode('c1')))
# insert again and this time delete the whole row, check that it is gone
client.add(key2, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
rv2 = client.get(key2, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv2.counter_column.value == d1
client.remove_counter(key2, ColumnPath(column_family='Counter1'), ConsistencyLevel.ONE)
_assert_no_columnpath(key2, ColumnPath(column_family='Counter1', column=utf8encode('c1')))
def test_incr_decr_super_remove(self, request):
_set_keyspace('Keyspace1')
key1 = utf8encode(request.node.name + "_1")
key2 = utf8encode(request.node.name + "_2")
d1 = 52345
# insert value and check it exists
client.add(key1, ColumnParent(column_family='SuperCounter1', super_column=utf8encode('sc1')), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
rv1 = client.get(key1, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv1.counter_column.value == d1
# remove the previous column and check that it is gone
client.remove_counter(key1, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')), ConsistencyLevel.ONE)
_assert_no_columnpath(key1, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')))
# insert again and this time delete the whole row, check that it is gone
client.add(key2, ColumnParent(column_family='SuperCounter1', super_column=utf8encode('sc1')), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
rv2 = client.get(key2, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv2.counter_column.value == d1
client.remove_counter(key2, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1')), ConsistencyLevel.ONE)
_assert_no_columnpath(key2, ColumnPath(column_family='SuperCounter1', super_column=utf8encode('sc1'), column=utf8encode('c1')))
def test_incr_decr_standard_batch_add(self, request):
_set_keyspace('Keyspace1')
key = utf8encode(request.node.name)
d1 = 12
d2 = -21
update_map = {key: {'Counter1': [
Mutation(column_or_supercolumn=ColumnOrSuperColumn(counter_column=CounterColumn(utf8encode('c1'), d1))),
Mutation(column_or_supercolumn=ColumnOrSuperColumn(counter_column=CounterColumn(utf8encode('c1'), d2))),
]}}
# insert positive and negative values and check the counts
client.batch_mutate(update_map, ConsistencyLevel.ONE)
rv1 = client.get(key, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv1.counter_column.value == d1 + d2
def test_incr_decr_standard_batch_remove(self, request):
_set_keyspace('Keyspace1')
key1 = utf8encode(request.node.name + "_1")
key2 = utf8encode(request.node.name + "_2")
d1 = 12
d2 = -21
# insert positive and negative values and check the counts
update_map = {key1: {'Counter1': [
Mutation(column_or_supercolumn=ColumnOrSuperColumn(counter_column=CounterColumn(utf8encode('c1'), d1))),
Mutation(column_or_supercolumn=ColumnOrSuperColumn(counter_column=CounterColumn(utf8encode('c1'), d2))),
]}}
client.batch_mutate(update_map, ConsistencyLevel.ONE)
rv1 = client.get(key1, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv1.counter_column.value == d1 + d2
# remove the previous column and check that it is gone
update_map = {key1: {'Counter1': [
Mutation(deletion=Deletion(predicate=SlicePredicate(column_names=[utf8encode('c1')]))),
]}}
client.batch_mutate(update_map, ConsistencyLevel.ONE)
_assert_no_columnpath(key1, ColumnPath(column_family='Counter1', column=utf8encode('c1')))
# insert again and this time delete the whole row, check that it is gone
update_map = {key2: {'Counter1': [
Mutation(column_or_supercolumn=ColumnOrSuperColumn(counter_column=CounterColumn(utf8encode('c1'), d1))),
Mutation(column_or_supercolumn=ColumnOrSuperColumn(counter_column=CounterColumn(utf8encode('c1'), d2))),
]}}
client.batch_mutate(update_map, ConsistencyLevel.ONE)
rv2 = client.get(key2, ColumnPath(column_family='Counter1', column=utf8encode('c1')), ConsistencyLevel.ONE)
assert rv2.counter_column.value == d1 + d2
update_map = {key2: {'Counter1': [
Mutation(deletion=Deletion()),
]}}
client.batch_mutate(update_map, ConsistencyLevel.ONE)
_assert_no_columnpath(key2, ColumnPath(column_family='Counter1', column=utf8encode('c1')))
# known failure: see CASSANDRA-10046
def test_range_deletion(self):
""" Tests CASSANDRA-7990 """
_set_keyspace('Keyspace1')
self.truncate_all('StandardComposite')
for i in range(10):
column_name = composite(str(i), str(i))
column = Column(column_name, utf8encode('value'), int(time.time() * 1000))
client.insert(utf8encode('key1'), ColumnParent('StandardComposite'), column, ConsistencyLevel.ONE)
delete_slice = SlicePredicate(slice_range=SliceRange(composite('3', eoc=b'\xff'), composite('6', b'\x01'), False, 100))
mutations = [Mutation(deletion=Deletion(int(time.time() * 1000), predicate=delete_slice))]
keyed_mutations = {utf8encode('key1'): {'StandardComposite': mutations}}
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
slice_predicate = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 100))
results = client.get_slice(utf8encode('key1'), ColumnParent('StandardComposite'), slice_predicate, ConsistencyLevel.ONE)
columns = [result.column.name for result in results]
assert columns == [composite('0', '0'), composite('1', '1'), composite('2', '2'),
composite('6', '6'), composite('7', '7'), composite('8', '8'), composite('9', '9')]
@pytest.mark.skip_version('3.9')
def test_range_deletion_eoc_0(self):
"""
This test confirms that a range tombstone with a final EOC of 0
results in a exclusive deletion except for cells that exactly match the tombstone bound.
@jira_ticket CASSANDRA-12423
"""
_set_keyspace('Keyspace1')
self.truncate_all('StandardComposite')
for i in range(10):
column_name = composite(str(i), str(i))
column = Column(column_name, utf8encode('value'), int(time.time() * 1000))
client.insert(utf8encode('key1'), ColumnParent('StandardComposite'), column, ConsistencyLevel.ONE)
# insert a partial cell name (just the first element of the composite)
column_name = composite('6', None, eoc=b'\x00')
column = Column(column_name, utf8encode('value'), int(time.time() * 1000))
client.insert(utf8encode('key1'), ColumnParent('StandardComposite'), column, ConsistencyLevel.ONE)
# sanity check the query
slice_predicate = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 100))
results = client.get_slice(utf8encode('key1'), ColumnParent('StandardComposite'), slice_predicate, ConsistencyLevel.ONE)
columns = [result.column.name for result in results]
assert columns == [composite('0', '0'), composite('1', '1'), composite('2', '2'), composite('3', '3'), composite('4', '4'), composite('5', '5'),
composite('6'),
composite('6', '6'),
composite('7', '7'), composite('8', '8'), composite('9', '9')]
# do a slice deletion with (6, ) as the end
delete_slice = SlicePredicate(slice_range=SliceRange(composite('3', eoc=b'\xff'), composite('6', b'\x00'), False, 100))
mutations = [Mutation(deletion=Deletion(int(time.time() * 1000), predicate=delete_slice))]
keyed_mutations = {utf8encode('key1'): {'StandardComposite': mutations}}
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
# check the columns post-deletion, (utf8encode('6'), ) because it is an exact much but not (6, 6)
results = client.get_slice(utf8encode('key1'), ColumnParent('StandardComposite'), slice_predicate, ConsistencyLevel.ONE)
columns = [result.column.name for result in results]
assert columns == [composite('0', '0'), composite('1', '1'), composite('2', '2'),
composite('6', '6'),
composite('7', '7'), composite('8', '8'), composite('9', '9')]
# do another slice deletion, but make the end (6, 6) this time
delete_slice = SlicePredicate(slice_range=SliceRange(composite('3', eoc=b'\xff'), composite('6', '6', b'\x00'), False, 100))
mutations = [Mutation(deletion=Deletion(int(time.time() * 1000), predicate=delete_slice))]
keyed_mutations = {utf8encode('key1'): {'StandardComposite': mutations}}
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
# check the columns post-deletion, now (6, 6) is also gone
results = client.get_slice(utf8encode('key1'), ColumnParent('StandardComposite'), slice_predicate, ConsistencyLevel.ONE)
columns = [result.column.name for result in results]
assert columns == [composite('0', '0'), composite('1', '1'), composite('2', '2'),
composite('7', '7'), composite('8', '8'), composite('9', '9')]
def test_incr_decr_standard_slice(self, request):
_set_keyspace('Keyspace1')
key = utf8encode(request.node.name)
d1 = 12
d2 = -21
client.add(key, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c1'), d1), ConsistencyLevel.ONE)
client.add(key, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c2'), d1), ConsistencyLevel.ONE)
client.add(key, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c3'), d1), ConsistencyLevel.ONE)
client.add(key, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c3'), d2), ConsistencyLevel.ONE)
client.add(key, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c4'), d1), ConsistencyLevel.ONE)
client.add(key, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c5'), d1), ConsistencyLevel.ONE)
# insert positive and negative values and check the counts
counters = client.get_slice(key, ColumnParent('Counter1'), SlicePredicate([utf8encode('c3'), utf8encode('c4')]), ConsistencyLevel.ONE)
assert counters[0].counter_column.value == d1 + d2
assert counters[1].counter_column.value == d1
def test_incr_decr_standard_multiget_slice(self, request):
_set_keyspace('Keyspace1')
key1 = utf8encode(request.node.name + "_1")
key2 = utf8encode(request.node.name + "_2")
d1 = 12
d2 = -21
client.add(key1, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c2'), d1), ConsistencyLevel.ONE)
client.add(key1, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c3'), d1), ConsistencyLevel.ONE)
client.add(key1, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c3'), d2), ConsistencyLevel.ONE)
client.add(key1, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c4'), d1), ConsistencyLevel.ONE)
client.add(key1, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c5'), d1), ConsistencyLevel.ONE)
client.add(key2, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c2'), d1), ConsistencyLevel.ONE)
client.add(key2, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c3'), d1), ConsistencyLevel.ONE)
client.add(key2, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c3'), d2), ConsistencyLevel.ONE)
client.add(key2, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c4'), d1), ConsistencyLevel.ONE)
client.add(key2, ColumnParent(column_family='Counter1'), CounterColumn(utf8encode('c5'), d1), ConsistencyLevel.ONE)
# insert positive and negative values and check the counts
counters = client.multiget_slice([key1, key2], ColumnParent('Counter1'), SlicePredicate([utf8encode('c3'), utf8encode('c4')]), ConsistencyLevel.ONE)
assert counters[key1][0].counter_column.value == d1 + d2
assert counters[key1][1].counter_column.value == d1
assert counters[key2][0].counter_column.value == d1 + d2
assert counters[key2][1].counter_column.value == d1
def test_counter_get_slice_range(self, request):
_set_keyspace('Keyspace1')
key = utf8encode(request.node.name)
client.add(key, ColumnParent('Counter1'), CounterColumn(utf8encode('c1'), 1), ConsistencyLevel.ONE)
client.add(key, ColumnParent('Counter1'), CounterColumn(utf8encode('c2'), 2), ConsistencyLevel.ONE)
client.add(key, ColumnParent('Counter1'), CounterColumn(utf8encode('c3'), 3), ConsistencyLevel.ONE)
p = SlicePredicate(slice_range=SliceRange(utf8encode('c1'), utf8encode('c2'), False, 1000))
result = client.get_slice(key, ColumnParent('Counter1'), p, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].counter_column.name == utf8encode('c1')
assert result[1].counter_column.name == utf8encode('c2')
p = SlicePredicate(slice_range=SliceRange(utf8encode('c3'), utf8encode('c2'), True, 1000))
result = client.get_slice(key, ColumnParent('Counter1'), p, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].counter_column.name == utf8encode('c3')
assert result[1].counter_column.name == utf8encode('c2')
p = SlicePredicate(slice_range=SliceRange(utf8encode('a'), utf8encode('z'), False, 1000))
result = client.get_slice(key, ColumnParent('Counter1'), p, ConsistencyLevel.ONE)
assert len(result) == 3, result
p = SlicePredicate(slice_range=SliceRange(utf8encode('a'), utf8encode('z'), False, 2))
result = client.get_slice(key, ColumnParent('Counter1'), p, ConsistencyLevel.ONE)
assert len(result) == 2, result
def test_counter_get_slice_super_range(self, request):
_set_keyspace('Keyspace1')
key = utf8encode(request.node.name)
client.add(key, ColumnParent('SuperCounter1', utf8encode('sc1')), CounterColumn(_i64(4), 4), ConsistencyLevel.ONE)
client.add(key, ColumnParent('SuperCounter1', utf8encode('sc2')), CounterColumn(_i64(5), 5), ConsistencyLevel.ONE)
client.add(key, ColumnParent('SuperCounter1', utf8encode('sc2')), CounterColumn(_i64(6), 6), ConsistencyLevel.ONE)
client.add(key, ColumnParent('SuperCounter1', utf8encode('sc3')), CounterColumn(_i64(7), 7), ConsistencyLevel.ONE)
p = SlicePredicate(slice_range=SliceRange(utf8encode('sc2'), utf8encode('sc3'), False, 2))
result = client.get_slice(key, ColumnParent('SuperCounter1'), p, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].counter_super_column.name == utf8encode('sc2')
assert result[1].counter_super_column.name == utf8encode('sc3')
p = SlicePredicate(slice_range=SliceRange(utf8encode('sc3'), utf8encode('sc2'), True, 2))
result = client.get_slice(key, ColumnParent('SuperCounter1'), p, ConsistencyLevel.ONE)
assert len(result) == 2
assert result[0].counter_super_column.name == utf8encode('sc3')
assert result[1].counter_super_column.name == utf8encode('sc2')
def test_index_scan(self):
_set_keyspace('Keyspace1')
self.truncate_all('Indexed1')
client.insert(utf8encode('key1'), ColumnParent('Indexed1'), Column(utf8encode('birthdate'), _i64(1), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key2'), ColumnParent('Indexed1'), Column(utf8encode('birthdate'), _i64(2), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key2'), ColumnParent('Indexed1'), Column(utf8encode('b'), _i64(2), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key3'), ColumnParent('Indexed1'), Column(utf8encode('birthdate'), _i64(3), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key3'), ColumnParent('Indexed1'), Column(utf8encode('b'), _i64(3), 0), ConsistencyLevel.ONE)
# simple query on one index expression
cp = ColumnParent('Indexed1')
sp = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode('')))
key_range = KeyRange(utf8encode(''), utf8encode(''), None, None, [IndexExpression(utf8encode('birthdate'), IndexOperator.EQ, _i64(1))], 100)
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 1, result
assert result[0].key == utf8encode('key1')
assert len(result[0].columns) == 1, result[0].columns
# without index
key_range = KeyRange(utf8encode(''), utf8encode(''), None, None, [IndexExpression(utf8encode('b'), IndexOperator.EQ, _i64(1))], 100)
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 0, result
# but unindexed expression added to indexed one is ok
key_range = KeyRange(utf8encode(''), utf8encode(''), None, None, [IndexExpression(utf8encode('b'), IndexOperator.EQ, _i64(3)), IndexExpression(utf8encode('birthdate'), IndexOperator.EQ, _i64(3))], 100)
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 1, result
assert result[0].key == utf8encode('key3')
assert len(result[0].columns) == 2, result[0].columns
def test_index_scan_uuid_names(self):
_set_keyspace('Keyspace1')
self.truncate_all('Indexed3')
sp = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode('')))
cp = ColumnParent('Indexed3') # timeuuid name, utf8 values
u = uuid.UUID('00000000-0000-1000-0000-000000000000').bytes
u2 = uuid.UUID('00000000-0000-1000-0000-000000000001').bytes
client.insert(utf8encode('key1'), ColumnParent('Indexed3'), Column(u, utf8encode('a'), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Indexed3'), Column(u2, utf8encode('b'), 0), ConsistencyLevel.ONE)
# name comparator + data validator of incompatible types -- see CASSANDRA-2347
key_range = KeyRange(utf8encode(''), utf8encode(''), None, None, [IndexExpression(u, IndexOperator.EQ, utf8encode('a')), IndexExpression(u2, IndexOperator.EQ, utf8encode('b'))], 100)
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 1, result
cp = ColumnParent('Indexed2') # timeuuid name, long values
# name must be valid (TimeUUID)
key_range = KeyRange(utf8encode(''), utf8encode(''), None, None, [IndexExpression(utf8encode('foo'), IndexOperator.EQ, uuid.UUID('00000000-0000-1000-0000-000000000000').bytes)], 100)
_expect_exception(lambda: client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE), InvalidRequestException)
# value must be valid (TimeUUID)
key_range = KeyRange(utf8encode(''), utf8encode(''), None, None, [IndexExpression(uuid.UUID('00000000-0000-1000-0000-000000000000').bytes, IndexOperator.EQ, utf8encode("foo"))], 100)
_expect_exception(lambda: client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE), InvalidRequestException)
def test_index_scan_expiring(self):
""" Test that column ttled expires from KEYS index"""
_set_keyspace('Keyspace1')
self.truncate_all('Indexed1')
client.insert(utf8encode('key1'), ColumnParent('Indexed1'), Column(utf8encode('birthdate'), _i64(1), 0, 2), ConsistencyLevel.ONE)
cp = ColumnParent('Indexed1')
sp = SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode('')))
key_range = KeyRange(utf8encode(''), utf8encode(''), None, None, [IndexExpression(utf8encode('birthdate'), IndexOperator.EQ, _i64(1))], 100)
# query before expiration
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 1, result
# wait for expiration and requery
time.sleep(3)
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 0, result
def test_index_scan_indexed_column_outside_slice_predicate(self):
"""
Verify that performing an indexed read works when the indexed column
is not included in the slice predicate. Checks both cases where the
predicate contains a slice range or a set of column names, which
translate to slice and names queries server-side.
@jira_ticket CASSANDRA-11523
"""
_set_keyspace('Keyspace1')
self.truncate_all('Indexed4')
client.insert(utf8encode('key1'), ColumnParent('Indexed4'), Column(utf8encode('a'), _i64(1), 0), ConsistencyLevel.ONE)
client.insert(utf8encode('key1'), ColumnParent('Indexed4'), Column(utf8encode('z'), utf8encode('zzz'), 0), ConsistencyLevel.ONE)
cp = ColumnParent('Indexed4')
sp = SlicePredicate(slice_range=SliceRange(utf8encode('z'), utf8encode('z')))
key_range = KeyRange(utf8encode(''), utf8encode(''), None, None, [IndexExpression(utf8encode('a'), IndexOperator.EQ, _i64(1))], 100)
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 1, result
assert len(result[0].columns) == 1, result[0].columns
assert result[0].columns[0].column.name == utf8encode('z')
sp = SlicePredicate(column_names=[utf8encode('z')])
result = client.get_range_slices(cp, sp, key_range, ConsistencyLevel.ONE)
assert len(result) == 1, result
assert len(result[0].columns) == 1, result[0].columns
assert result[0].columns[0].column.name == utf8encode('z')
def test_column_not_found_quorum(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
key = utf8encode('doesntexist')
column_path = ColumnPath(column_family="Standard1", column=utf8encode("idontexist"))
try:
client.get(key, column_path, ConsistencyLevel.QUORUM)
assert False, ('columnpath %s existed in %s when it should not' % (column_path, key))
except NotFoundException:
assert True, 'column did not exist'
def test_get_range_slice_after_deletion(self):
_set_keyspace('Keyspace2')
self.truncate_all('Super3')
key = utf8encode('key1')
# three supercoluns, each with "col1" subcolumn
for i in range(1, 4):
client.insert(key, ColumnParent('Super3', utf8encode('sc%d' % i)), Column(utf8encode('col1'), utf8encode('val1'), 0), ConsistencyLevel.ONE)
cp = ColumnParent('Super3')
predicate = SlicePredicate(slice_range=SliceRange(utf8encode('sc1'), utf8encode('sc3'), False, count=1))
k_range = KeyRange(start_key=key, end_key=key, count=1)
# validate count=1 restricts to 1 supercolumn
result = client.get_range_slices(cp, predicate, k_range, ConsistencyLevel.ONE)
assert len(result[0].columns) == 1
# remove sc1; add back subcolumn to override tombstone
client.remove(key, ColumnPath('Super3', utf8encode('sc1')), 1, ConsistencyLevel.ONE)
result = client.get_range_slices(cp, predicate, k_range, ConsistencyLevel.ONE)
assert len(result[0].columns) == 1
client.insert(key, ColumnParent('Super3', utf8encode('sc1')), Column(utf8encode('col1'), utf8encode('val1'), 2), ConsistencyLevel.ONE)
result = client.get_range_slices(cp, predicate, k_range, ConsistencyLevel.ONE)
assert len(result[0].columns) == 1, result[0].columns
assert result[0].columns[0].super_column.name == utf8encode('sc1')
def test_multi_slice(self):
_set_keyspace('Keyspace1')
self.truncate_all('Standard1')
_insert_six_columns('abc')
L = [result.column
for result in _big_multi_slice('abc')]
assert L == _MULTI_SLICE_COLUMNS, L
def test_truncate(self):
_set_keyspace('Keyspace1')
_insert_simple()
_insert_super()
# truncate Standard1
self.truncate_all('Standard1')
assert _big_slice(utf8encode('key1'), ColumnParent('Standard1')) == []
# truncate Super1
self.truncate_all('Super1')
assert _big_slice(utf8encode('key1'), ColumnParent('Super1')) == []
assert _big_slice(utf8encode('key1'), ColumnParent('Super1', utf8encode('sc1'))) == []
@since('3.0', max_version='4')
def test_cql_range_tombstone_and_static(self):
node1 = self.cluster.nodelist()[0]
session = self.patient_cql_connection(node1)
# Create a CQL table with a static column and insert a row
session.execute('USE "Keyspace1"')
session.execute("CREATE TABLE t (k text, s text static, t text, v text, PRIMARY KEY (k, t))")
session.execute("INSERT INTO t (k, s, t, v) VALUES ('k', 's', 't', 'v') USING TIMESTAMP 0")
assert_one(session, "SELECT * FROM t", ['k', 't', 's', 'v'])
# Now submit a range deletion that should include both the row and the static value
_set_keyspace('Keyspace1')
mutations = [Mutation(deletion=Deletion(1, predicate=SlicePredicate(slice_range=SliceRange(utf8encode(''), utf8encode(''), False, 1000))))]
mutation_map = dict((table, mutations) for table in ['t'])
keyed_mutations = dict((key, mutation_map) for key in [utf8encode('k')])
client.batch_mutate(keyed_mutations, ConsistencyLevel.ONE)
# And check everything is gone
assert_none(session, "SELECT * FROM t")
def test_compact_storage_get(self):
node1 = self.cluster.nodelist()[0]
session = self.patient_cql_connection(node1)
# Create a CQL table with a static column and insert a row
session.execute("USE \"Keyspace1\"")
session.execute("CREATE TABLE IF NOT EXISTS cs1 (k int PRIMARY KEY,v int) WITH COMPACT STORAGE")
_set_keyspace('Keyspace1')
CL = ConsistencyLevel.ONE
i = 1
client.insert(_i32(i), ColumnParent('cs1'), Column(utf8encode('v'), _i32(i), 0), CL)
_assert_column('cs1', _i32(i), utf8encode('v'), _i32(i), 0)
@pytest.mark.skip_version('3.9')
def test_range_tombstone_eoc_0(self):
"""
Insert a range tombstone with EOC=0 for a compact storage table. Insert 2 rows that
are just outside the range and check that they are present.
@jira_ticket CASSANDRA-12423
"""
node1 = self.cluster.nodelist()[0]
session = self.patient_cql_connection(node1)
session.execute('USE "Keyspace1"')
session.execute("CREATE TABLE test (id INT, c1 TEXT, c2 TEXT, v INT, PRIMARY KEY (id, c1, c2)) "
"with compact storage and compression = {'sstable_compression': ''};")
_set_keyspace('Keyspace1')
range_delete = {
_i32(1): {
'test': [Mutation(deletion=Deletion(2470761440040513,
predicate=SlicePredicate(slice_range=SliceRange(
start=composite('a'), finish=composite('asd')))))]
}
}
client.batch_mutate(range_delete, ConsistencyLevel.ONE)
session.execute("INSERT INTO test (id, c1, c2, v) VALUES (1, 'asd', '', 0) USING TIMESTAMP 1470761451368658")
session.execute("INSERT INTO test (id, c1, c2, v) VALUES (1, 'asd', 'asd', 0) USING TIMESTAMP 1470761449416613")
ret = list(session.execute('SELECT * FROM test'))
assert 2 == len(ret)
node1.nodetool('flush Keyspace1 test')