
create_keyspace no longer has defaults for SimpleStrategy and replication factor. changed tests to use the default keyspace, cqlengine_test for all tests. Not sure why other keyspaces were being used.
293 lines
9.8 KiB
Python
293 lines
9.8 KiB
Python
import mock
|
|
from cqlengine import ALL, CACHING_ALL, CACHING_NONE
|
|
from cqlengine.connection import get_session
|
|
from cqlengine.exceptions import CQLEngineException
|
|
from cqlengine.management import get_fields, sync_table, drop_table
|
|
from cqlengine.tests.base import BaseCassEngTestCase
|
|
from cqlengine.tests.base import CASSANDRA_VERSION, PROTOCOL_VERSION
|
|
from cqlengine import management
|
|
from cqlengine.tests.query.test_queryset import TestModel
|
|
from cqlengine.models import Model
|
|
from cqlengine import columns, SizeTieredCompactionStrategy, LeveledCompactionStrategy
|
|
from unittest import skipUnless
|
|
|
|
|
|
class CreateKeyspaceTest(BaseCassEngTestCase):
|
|
def test_create_succeeeds(self):
|
|
management.create_keyspace('test_keyspace', strategy_class="SimpleStrategy", replication_factor=1)
|
|
management.delete_keyspace('test_keyspace')
|
|
|
|
class DeleteTableTest(BaseCassEngTestCase):
|
|
|
|
def test_multiple_deletes_dont_fail(self):
|
|
"""
|
|
|
|
"""
|
|
sync_table(TestModel)
|
|
|
|
drop_table(TestModel)
|
|
drop_table(TestModel)
|
|
|
|
class LowercaseKeyModel(Model):
|
|
|
|
first_key = columns.Integer(primary_key=True)
|
|
second_key = columns.Integer(primary_key=True)
|
|
some_data = columns.Text()
|
|
|
|
class CapitalizedKeyModel(Model):
|
|
|
|
firstKey = columns.Integer(primary_key=True)
|
|
secondKey = columns.Integer(primary_key=True)
|
|
someData = columns.Text()
|
|
|
|
class PrimaryKeysOnlyModel(Model):
|
|
|
|
__compaction__ = LeveledCompactionStrategy
|
|
|
|
first_ey = columns.Integer(primary_key=True)
|
|
second_key = columns.Integer(primary_key=True)
|
|
|
|
|
|
class CapitalizedKeyTest(BaseCassEngTestCase):
|
|
|
|
def test_table_definition(self):
|
|
""" Tests that creating a table with capitalized column names succeedso """
|
|
sync_table(LowercaseKeyModel)
|
|
sync_table(CapitalizedKeyModel)
|
|
|
|
drop_table(LowercaseKeyModel)
|
|
drop_table(CapitalizedKeyModel)
|
|
|
|
|
|
class FirstModel(Model):
|
|
|
|
__table_name__ = 'first_model'
|
|
first_key = columns.UUID(primary_key=True)
|
|
second_key = columns.UUID()
|
|
third_key = columns.Text()
|
|
|
|
class SecondModel(Model):
|
|
|
|
__table_name__ = 'first_model'
|
|
first_key = columns.UUID(primary_key=True)
|
|
second_key = columns.UUID()
|
|
third_key = columns.Text()
|
|
fourth_key = columns.Text()
|
|
|
|
class ThirdModel(Model):
|
|
|
|
__table_name__ = 'first_model'
|
|
first_key = columns.UUID(primary_key=True)
|
|
second_key = columns.UUID()
|
|
third_key = columns.Text()
|
|
# removed fourth key, but it should stay in the DB
|
|
blah = columns.Map(columns.Text, columns.Text)
|
|
|
|
class FourthModel(Model):
|
|
|
|
__table_name__ = 'first_model'
|
|
first_key = columns.UUID(primary_key=True)
|
|
second_key = columns.UUID()
|
|
third_key = columns.Text()
|
|
# removed fourth key, but it should stay in the DB
|
|
renamed = columns.Map(columns.Text, columns.Text, db_field='blah')
|
|
|
|
class AddColumnTest(BaseCassEngTestCase):
|
|
def setUp(self):
|
|
drop_table(FirstModel)
|
|
|
|
def test_add_column(self):
|
|
sync_table(FirstModel)
|
|
fields = get_fields(FirstModel)
|
|
|
|
# this should contain the second key
|
|
self.assertEqual(len(fields), 2)
|
|
# get schema
|
|
sync_table(SecondModel)
|
|
|
|
fields = get_fields(FirstModel)
|
|
self.assertEqual(len(fields), 3)
|
|
|
|
sync_table(ThirdModel)
|
|
fields = get_fields(FirstModel)
|
|
self.assertEqual(len(fields), 4)
|
|
|
|
sync_table(FourthModel)
|
|
fields = get_fields(FirstModel)
|
|
self.assertEqual(len(fields), 4)
|
|
|
|
|
|
class ModelWithTableProperties(Model):
|
|
|
|
# Set random table properties
|
|
__bloom_filter_fp_chance__ = 0.76328
|
|
__caching__ = CACHING_ALL
|
|
__comment__ = 'TxfguvBdzwROQALmQBOziRMbkqVGFjqcJfVhwGR'
|
|
__gc_grace_seconds__ = 2063
|
|
__populate_io_cache_on_flush__ = True
|
|
__read_repair_chance__ = 0.17985
|
|
__replicate_on_write__ = False
|
|
__dclocal_read_repair_chance__ = 0.50811
|
|
|
|
key = columns.UUID(primary_key=True)
|
|
|
|
# kind of a hack, but we only test this property on C >= 2.0
|
|
if CASSANDRA_VERSION >= 20:
|
|
ModelWithTableProperties.__memtable_flush_period_in_ms__ = 43681
|
|
ModelWithTableProperties.__index_interval__ = 98706
|
|
ModelWithTableProperties.__default_time_to_live__ = 4756
|
|
|
|
class TablePropertiesTests(BaseCassEngTestCase):
|
|
|
|
def setUp(self):
|
|
drop_table(ModelWithTableProperties)
|
|
|
|
def test_set_table_properties(self):
|
|
|
|
sync_table(ModelWithTableProperties)
|
|
expected = {'bloom_filter_fp_chance': 0.76328,
|
|
'comment': 'TxfguvBdzwROQALmQBOziRMbkqVGFjqcJfVhwGR',
|
|
'gc_grace_seconds': 2063,
|
|
'read_repair_chance': 0.17985,
|
|
# For some reason 'dclocal_read_repair_chance' in CQL is called
|
|
# just 'local_read_repair_chance' in the schema table.
|
|
# Source: https://issues.apache.org/jira/browse/CASSANDRA-6717
|
|
# TODO: due to a bug in the native driver i'm not seeing the local read repair chance show up
|
|
# 'local_read_repair_chance': 0.50811,
|
|
}
|
|
if CASSANDRA_VERSION <= 20:
|
|
expected['caching'] = CACHING_ALL
|
|
expected['replicate_on_write'] = False
|
|
|
|
if CASSANDRA_VERSION == 20:
|
|
expected['populate_io_cache_on_flush'] = True
|
|
expected['index_interval'] = 98706
|
|
|
|
if CASSANDRA_VERSION >= 20:
|
|
expected['default_time_to_live'] = 4756
|
|
expected['memtable_flush_period_in_ms'] = 43681
|
|
|
|
self.assertDictContainsSubset(expected, management.get_table_settings(ModelWithTableProperties).options)
|
|
|
|
def test_table_property_update(self):
|
|
ModelWithTableProperties.__bloom_filter_fp_chance__ = 0.66778
|
|
ModelWithTableProperties.__caching__ = CACHING_NONE
|
|
ModelWithTableProperties.__comment__ = 'xirAkRWZVVvsmzRvXamiEcQkshkUIDINVJZgLYSdnGHweiBrAiJdLJkVohdRy'
|
|
ModelWithTableProperties.__gc_grace_seconds__ = 96362
|
|
|
|
ModelWithTableProperties.__populate_io_cache_on_flush__ = False
|
|
ModelWithTableProperties.__read_repair_chance__ = 0.2989
|
|
ModelWithTableProperties.__replicate_on_write__ = True
|
|
ModelWithTableProperties.__dclocal_read_repair_chance__ = 0.12732
|
|
|
|
if CASSANDRA_VERSION >= 20:
|
|
ModelWithTableProperties.__default_time_to_live__ = 65178
|
|
ModelWithTableProperties.__memtable_flush_period_in_ms__ = 60210
|
|
ModelWithTableProperties.__index_interval__ = 94207
|
|
|
|
sync_table(ModelWithTableProperties)
|
|
|
|
table_settings = management.get_table_settings(ModelWithTableProperties).options
|
|
|
|
expected = {'bloom_filter_fp_chance': 0.66778,
|
|
'comment': 'xirAkRWZVVvsmzRvXamiEcQkshkUIDINVJZgLYSdnGHweiBrAiJdLJkVohdRy',
|
|
'gc_grace_seconds': 96362,
|
|
'read_repair_chance': 0.2989,
|
|
#'local_read_repair_chance': 0.12732,
|
|
}
|
|
if CASSANDRA_VERSION >= 20:
|
|
expected['memtable_flush_period_in_ms'] = 60210
|
|
expected['default_time_to_live'] = 65178
|
|
|
|
if CASSANDRA_VERSION == 20:
|
|
expected['index_interval'] = 94207
|
|
|
|
# these featuers removed in cassandra 2.1
|
|
if CASSANDRA_VERSION <= 20:
|
|
expected['caching'] = CACHING_NONE
|
|
expected['replicate_on_write'] = True
|
|
expected['populate_io_cache_on_flush'] = False
|
|
|
|
self.assertDictContainsSubset(expected, table_settings)
|
|
|
|
|
|
class SyncTableTests(BaseCassEngTestCase):
|
|
|
|
def setUp(self):
|
|
drop_table(PrimaryKeysOnlyModel)
|
|
|
|
def test_sync_table_works_with_primary_keys_only_tables(self):
|
|
|
|
# This is "create table":
|
|
|
|
sync_table(PrimaryKeysOnlyModel)
|
|
|
|
# let's make sure settings persisted correctly:
|
|
|
|
assert PrimaryKeysOnlyModel.__compaction__ == LeveledCompactionStrategy
|
|
# blows up with DoesNotExist if table does not exist
|
|
table_settings = management.get_table_settings(PrimaryKeysOnlyModel)
|
|
# let make sure the flag we care about
|
|
|
|
assert LeveledCompactionStrategy in table_settings.options['compaction_strategy_class']
|
|
|
|
|
|
# Now we are "updating" the table:
|
|
|
|
# setting up something to change
|
|
PrimaryKeysOnlyModel.__compaction__ = SizeTieredCompactionStrategy
|
|
|
|
# primary-keys-only tables do not create entries in system.schema_columns
|
|
# table. Only non-primary keys are added to that table.
|
|
# Our code must deal with that eventuality properly (not crash)
|
|
# on subsequent runs of sync_table (which runs get_fields internally)
|
|
get_fields(PrimaryKeysOnlyModel)
|
|
sync_table(PrimaryKeysOnlyModel)
|
|
|
|
table_settings = management.get_table_settings(PrimaryKeysOnlyModel)
|
|
assert SizeTieredCompactionStrategy in table_settings.options['compaction_strategy_class']
|
|
|
|
class NonModelFailureTest(BaseCassEngTestCase):
|
|
class FakeModel(object):
|
|
pass
|
|
|
|
def test_failure(self):
|
|
with self.assertRaises(CQLEngineException):
|
|
sync_table(self.FakeModel)
|
|
|
|
|
|
@skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0")
|
|
def test_static_columns():
|
|
class StaticModel(Model):
|
|
id = columns.Integer(primary_key=True)
|
|
c = columns.Integer(primary_key=True)
|
|
name = columns.Text(static=True)
|
|
|
|
drop_table(StaticModel)
|
|
|
|
from mock import patch
|
|
|
|
from cqlengine.connection import get_session
|
|
session = get_session()
|
|
|
|
with patch.object(session, "execute", wraps=session.execute) as m:
|
|
sync_table(StaticModel)
|
|
|
|
assert m.call_count > 0
|
|
statement = m.call_args[0][0].query_string
|
|
assert '"name" text static' in statement, statement
|
|
|
|
# if we sync again, we should not apply an alter w/ a static
|
|
sync_table(StaticModel)
|
|
|
|
with patch.object(session, "execute", wraps=session.execute) as m2:
|
|
sync_table(StaticModel)
|
|
|
|
assert len(m2.call_args_list) == 1
|
|
assert "ALTER" not in m2.call_args[0][0].query_string
|
|
|
|
|
|
|
|
|
|
|