Merge pull request #408 from datastax/improved_metadata_test

Adding tests for Materialized views. Fixing issues associated with test timeouts and other small changes.
This commit is contained in:
Greg Bestland
2015-10-09 13:09:21 -05:00
7 changed files with 429 additions and 117 deletions

View File

@@ -25,7 +25,7 @@ build:
sudo apt-get install -y libev4 libev-dev
fi
pip install -r test-requirements.txt
pip install nose-ignore-docstring
if [[ $CYTHON == 'CYTHON' ]]; then
pip install cython
@@ -38,12 +38,12 @@ build:
fi
echo "==========RUNNING CQLENGINE TESTS=========="
CASSANDRA_VERSION=$CCM_CASSANDRA_VERSION nosetests -s -v --with-xunit --xunit-file=cqle_results.xml tests/integration/cqlengine/ || true
CASSANDRA_VERSION=$CCM_CASSANDRA_VERSION nosetests -s -v --logging-format="[%(levelname)s] %(asctime)s %(thread)d: %(message)s" --with-ignore-docstrings --with-xunit --xunit-file=cqle_results.xml tests/integration/cqlengine/ || true
echo "==========RUNNING INTEGRATION TESTS=========="
CASSANDRA_VERSION=$CCM_CASSANDRA_VERSION nosetests -s -v --with-xunit --xunit-file=standard_results.xml tests/integration/standard/ || true
CASSANDRA_VERSION=$CCM_CASSANDRA_VERSION nosetests -s -v --logging-format="[%(levelname)s] %(asctime)s %(thread)d: %(message)s" --with-ignore-docstrings --with-xunit --xunit-file=standard_results.xml tests/integration/standard/ || true
echo "==========RUNNING LONG INTEGRATION TESTS=========="
CASSANDRA_VERSION=$CCM_CASSANDRA_VERSION nosetests -s -v --with-xunit --xunit-file=long_results.xml tests/integration/long/ || true
CASSANDRA_VERSION=$CCM_CASSANDRA_VERSION nosetests -s -v --logging-format="[%(levelname)s] %(asctime)s %(thread)d: %(message)s" --with-ignore-docstrings --with-xunit --xunit-file=long_results.xml tests/integration/long/ || true
- xunit:
- "*_results.xml"

View File

@@ -271,6 +271,7 @@ def execute_until_pass(session, query):
raise RuntimeError("Failed to execute query after 100 attempts: {0}".format(query))
def setup_keyspace(ipformat=None):
# wait for nodes to startup
time.sleep(10)
@@ -332,3 +333,149 @@ class UpDownWaiter(object):
def wait_for_up(self):
self.up_event.wait()
class BasicKeyspaceUnitTestCase(unittest.TestCase):
"""
This is basic unit test case that provides various utility methods that can be leveraged for testcase setup and tear
down
"""
@property
def keyspace_name(self):
return self.ks_name
@property
def class_table_name(self):
return self.ks_name
@property
def function_table_name(self):
return self._testMethodName.lower()
@classmethod
def drop_keyspace(cls):
execute_until_pass(cls.session, "DROP KEYSPACE {0}".format(cls.ks_name))
@classmethod
def create_keyspace(cls, rf):
ddl = "CREATE KEYSPACE {0} WITH replication = {{'class': 'SimpleStrategy', 'replication_factor': '{1}'}}".format(cls.ks_name, rf)
execute_until_pass(cls.session, ddl)
@classmethod
def common_setup(cls, rf, create_class_table=False, skip_if_cass_version_less_than=None):
cls.cluster = Cluster(protocol_version=PROTOCOL_VERSION)
cls.session = cls.cluster.connect()
cls.ks_name = cls.__name__.lower()
cls.create_keyspace(rf)
if create_class_table:
ddl = '''
CREATE TABLE {0}.{1} (
k int PRIMARY KEY,
v int )'''.format(cls.ks_name, cls.ks_name)
execute_until_pass(cls.session, ddl)
def create_function_table(self):
ddl = '''
CREATE TABLE {0}.{1} (
k int PRIMARY KEY,
v int )'''.format(self.keyspace_name, self.function_table_name)
execute_until_pass(self.session, ddl)
def drop_function_table(self):
ddl = "DROP TABLE {0}.{1} ".format(self.keyspace_name, self.function_table_name)
execute_until_pass(self.session, ddl)
class BasicSharedKeyspaceUnitTestCase(BasicKeyspaceUnitTestCase):
"""
This is basic unit test case that can be leveraged to scope a keyspace to a specific test class.
creates a keyspace named after the testclass with a rf of 1.
"""
@classmethod
def setUpClass(cls):
cls.common_setup(1)
@classmethod
def tearDownClass(cls):
cls.drop_keyspace()
cls.cluster.shutdown()
class BasicSharedKeyspaceUnitTestCaseWTable(BasicSharedKeyspaceUnitTestCase):
"""
This is basic unit test case that can be leveraged to scope a keyspace to a specific test class.
creates a keyspace named after the testclass with a rf of 1, and a table named after the class
"""
@classmethod
def setUpClass(self):
self.common_setup(1, True)
class BasicSharedKeyspaceUnitTestCaseRF2(BasicSharedKeyspaceUnitTestCase):
"""
This is basic unit test case that can be leveraged to scope a keyspace to a specific test class.
creates a keyspace named after the test class with a rf of 2, and a table named after the class
"""
@classmethod
def setUpClass(self):
self.common_setup(2)
class BasicSharedKeyspaceUnitTestCaseWTable(BasicSharedKeyspaceUnitTestCase):
"""
This is basic unit test case that can be leveraged to scope a keyspace to a specific test class.
creates a keyspace named after the testc lass with a rf of 2, and a table named after the class
"""
@classmethod
def setUpClass(self):
self.common_setup(2, True)
class BasicSharedKeyspaceUnitTestCaseRF3(BasicSharedKeyspaceUnitTestCase):
"""
This is basic unit test case that can be leveraged to scope a keyspace to a specific test class.
creates a keyspace named after the test class with a rf of 3
"""
@classmethod
def setUpClass(self):
self.common_setup(3)
class BasicSharedKeyspaceUnitTestCaseRF3WTable(BasicSharedKeyspaceUnitTestCase):
"""
This is basic unit test case that can be leveraged to scope a keyspace to a specific test class.
creates a keyspace named after the test class with a rf of 3 and a table named after the class
"""
@classmethod
def setUpClass(self):
self.common_setup(3, True)
class BasicSharedKeyspaceUnitTestCaseWFunctionTable(BasicSharedKeyspaceUnitTestCase):
""""
This is basic unit test case that can be leveraged to scope a keyspace to a specific test class.
creates a keyspace named after the test class with a rf of 3 and a table named after the class
the table is scoped to just the unit test and will be removed.
"""
def setUp(self):
self.create_function_table()
def tearDown(self):
self.drop_function_table()
class BasicSegregatedKeyspaceUnitTestCase(BasicKeyspaceUnitTestCase):
"""
This unit test will create and teardown a keyspace for each individual unit tests.
It has overhead and should only be used with complex unit test were sharing a keyspace will
cause issues.
"""
def setUp(self):
self.common_setup(1)
def tearDown(self):
self.drop_keyspace()
self.cluster.shutdown()

View File

@@ -12,6 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
try:
import unittest2 as unittest
except ImportError:
import unittest # noqa
from cassandra.cqlengine.management import sync_table, drop_table
from tests.integration.cqlengine.base import BaseCassEngTestCase
from cassandra.cqlengine.models import Model
@@ -19,6 +25,7 @@ from uuid import uuid4
from cassandra.cqlengine import columns
import mock
from cassandra.cqlengine.connection import get_session
from tests.integration import CASSANDRA_VERSION
class TestTTLModel(Model):
@@ -51,12 +58,14 @@ class BaseDefaultTTLTest(BaseCassEngTestCase):
@classmethod
def setUpClass(cls):
if CASSANDRA_VERSION >= '2.0':
super(BaseDefaultTTLTest, cls).setUpClass()
sync_table(TestDefaultTTLModel)
sync_table(TestTTLModel)
@classmethod
def tearDownClass(cls):
if CASSANDRA_VERSION >= '2.0':
super(BaseDefaultTTLTest, cls).tearDownClass()
drop_table(TestDefaultTTLModel)
drop_table(TestTTLModel)
@@ -91,7 +100,6 @@ class TTLModelTests(BaseTTLTest):
self.assertTrue(isinstance(qs, TestTTLModel.__queryset__), type(qs))
class TTLInstanceUpdateTest(BaseTTLTest):
def test_update_includes_ttl(self):
session = get_session()
@@ -109,9 +117,6 @@ class TTLInstanceUpdateTest(BaseTTLTest):
model.ttl(60).update(text="goodbye forever")
class TTLInstanceTest(BaseTTLTest):
def test_instance_is_returned(self):
"""
@@ -151,6 +156,7 @@ class TTLBlindUpdateTest(BaseTTLTest):
self.assertIn("USING TTL", query)
@unittest.skipIf(CASSANDRA_VERSION < '2.0', "default_time_to_Live was introduce in C* 2.0, currently running {0}".format(CASSANDRA_VERSION))
class TTLDefaultTest(BaseDefaultTTLTest):
def test_default_ttl_not_set(self):
session = get_session()

View File

@@ -503,7 +503,7 @@ class ClusterTests(unittest.TestCase):
cluster.shutdown()
def test_idle_heartbeat(self):
interval = 1
interval = 2
cluster = Cluster(protocol_version=PROTOCOL_VERSION, idle_heartbeat_interval=interval)
if PROTOCOL_VERSION < 3:
cluster.set_core_connections_per_host(HostDistance.LOCAL, 1)
@@ -520,7 +520,7 @@ class ClusterTests(unittest.TestCase):
connection_request_ids[id(c)] = deque(c.request_ids) # copy of request ids
# let two heatbeat intervals pass (first one had startup messages in it)
time.sleep(2 * interval + interval/10.)
time.sleep(2 * interval + interval/2)
connections = [c for holders in cluster.get_connection_holders() for c in holders.get_connections()]

View File

@@ -32,8 +32,10 @@ from cassandra.metadata import (Metadata, KeyspaceMetadata, IndexMetadata, Index
get_schema_parser)
from cassandra.policies import SimpleConvictionPolicy
from cassandra.pool import Host
from cassandra.query import SimpleStatement, ConsistencyLevel
from tests.integration import get_cluster, use_singledc, PROTOCOL_VERSION, get_server_versions, execute_until_pass
from tests.integration import get_cluster, use_singledc, PROTOCOL_VERSION, get_server_versions, execute_until_pass, \
BasicSharedKeyspaceUnitTestCase, BasicSegregatedKeyspaceUnitTestCase
def setup_module():
@@ -307,8 +309,8 @@ class SchemaMetadataTests(unittest.TestCase):
statements = [s.strip() for s in statements.split(';')]
statements = list(filter(bool, statements))
self.assertEqual(3, len(statements))
self.assertEqual(d_index, statements[1])
self.assertEqual(e_index, statements[2])
self.assertIn(d_index, statements)
self.assertIn(e_index, statements)
# make sure indexes are included in KeyspaceMetadata.export_as_string()
ksmeta = self.cluster.metadata.keyspaces[self.ksname]
@@ -1901,23 +1903,17 @@ class BadMetaTest(unittest.TestCase):
self.assertIn("/*\nWarning:", m.export_as_string())
class MaterializedViewMetadataTest(unittest.TestCase):
ksname = "materialized_view_test"
class MaterializedViewMetadataTestSimple(BasicSharedKeyspaceUnitTestCase):
def setUp(self):
if CASS_SERVER_VERSION < (3, 0):
raise unittest.SkipTest("Materialized views require Cassandra 3.0+")
self.cluster = Cluster(protocol_version=PROTOCOL_VERSION)
self.session = self.cluster.connect()
execute_until_pass(self.session,
"CREATE KEYSPACE {0} WITH replication = {{'class': 'SimpleStrategy', 'replication_factor': '1'}}"
.format(self.ksname))
self.session.execute("CREATE TABLE {0}.{1} (pk int PRIMARY KEY, c int)".format(self.keyspace_name, self.function_table_name))
self.session.execute("CREATE MATERIALIZED VIEW {0}.mv1 AS SELECT c FROM {0}.{1} WHERE c IS NOT NULL PRIMARY KEY (pk, c)".format(self.keyspace_name, self.function_table_name))
def tearDown(self):
execute_until_pass(self.session, "DROP KEYSPACE {0}".format(self.ksname))
self.cluster.shutdown()
self.session.execute("DROP MATERIALIZED VIEW {0}.mv1".format(self.keyspace_name))
self.session.execute("DROP TABLE {0}.{1}".format(self.keyspace_name, self.function_table_name))
def test_materialized_view_metadata_creation(self):
"""
@@ -1935,14 +1931,11 @@ class MaterializedViewMetadataTest(unittest.TestCase):
@test_category metadata
"""
self.session.execute("CREATE TABLE {0}.table1 (pk int PRIMARY KEY, c int)".format(self.ksname))
self.session.execute("CREATE MATERIALIZED VIEW {0}.mv1 AS SELECT c FROM {0}.table1 WHERE c IS NOT NULL PRIMARY KEY (pk, c)".format(self.ksname))
self.assertIn("mv1", self.cluster.metadata.keyspaces[self.keyspace_name].views)
self.assertIn("mv1", self.cluster.metadata.keyspaces[self.keyspace_name].tables[self.function_table_name].views)
self.assertIn("mv1", self.cluster.metadata.keyspaces[self.ksname].views)
self.assertIn("mv1", self.cluster.metadata.keyspaces[self.ksname].tables["table1"].views)
self.assertEqual(self.ksname, self.cluster.metadata.keyspaces[self.ksname].tables["table1"].views["mv1"].keyspace_name)
self.assertEqual("table1", self.cluster.metadata.keyspaces[self.ksname].tables["table1"].views["mv1"].base_table_name)
self.assertEqual(self.keyspace_name, self.cluster.metadata.keyspaces[self.keyspace_name].tables[self.function_table_name].views["mv1"].keyspace_name)
self.assertEqual(self.function_table_name, self.cluster.metadata.keyspaces[self.keyspace_name].tables[self.function_table_name].views["mv1"].base_table_name)
def test_materialized_view_metadata_alter(self):
"""
@@ -1959,15 +1952,10 @@ class MaterializedViewMetadataTest(unittest.TestCase):
@test_category metadata
"""
self.assertIn("SizeTieredCompactionStrategy", self.cluster.metadata.keyspaces[self.keyspace_name].tables[self.function_table_name].views["mv1"].options["compaction"]["class"] )
self.session.execute("CREATE TABLE {0}.table1 (pk int PRIMARY KEY, c int)".format(self.ksname))
self.session.execute("CREATE MATERIALIZED VIEW {0}.mv1 AS SELECT c FROM {0}.table1 WHERE c IS NOT NULL PRIMARY KEY (pk, c)".format(self.ksname))
self.assertIn("SizeTieredCompactionStrategy", self.cluster.metadata.keyspaces[self.ksname].tables["table1"].views["mv1"].options["compaction"]["class"])
self.session.execute("ALTER MATERIALIZED VIEW {0}.mv1 WITH compaction = {{ 'class' : 'LeveledCompactionStrategy' }}".format(self.ksname))
self.assertIn("LeveledCompactionStrategy", self.cluster.metadata.keyspaces[self.ksname].tables["table1"].views["mv1"].options["compaction"]["class"])
self.session.execute("ALTER MATERIALIZED VIEW {0}.mv1 WITH compaction = {{ 'class' : 'LeveledCompactionStrategy' }}".format(self.keyspace_name))
self.assertIn("LeveledCompactionStrategy", self.cluster.metadata.keyspaces[self.keyspace_name].tables[self.function_table_name].views["mv1"].options["compaction"]["class"])
def test_materialized_view_metadata_drop(self):
"""
@@ -1985,14 +1973,21 @@ class MaterializedViewMetadataTest(unittest.TestCase):
@test_category metadata
"""
self.session.execute("CREATE TABLE {0}.table1 (pk int PRIMARY KEY, c int)".format(self.ksname))
self.session.execute("CREATE MATERIALIZED VIEW {0}.mv1 AS SELECT c FROM {0}.table1 WHERE c IS NOT NULL PRIMARY KEY (pk, c)".format(self.ksname))
self.session.execute("DROP MATERIALIZED VIEW {0}.mv1".format(self.ksname))
self.session.execute("DROP MATERIALIZED VIEW {0}.mv1".format(self.keyspace_name))
self.assertNotIn("mv1", self.cluster.metadata.keyspaces[self.ksname].tables["table1"].views)
self.assertNotIn("mv1", self.cluster.metadata.keyspaces[self.ksname].views)
self.assertDictEqual({}, self.cluster.metadata.keyspaces[self.ksname].tables["table1"].views)
self.assertDictEqual({}, self.cluster.metadata.keyspaces[self.ksname].views)
self.assertNotIn("mv1", self.cluster.metadata.keyspaces[self.keyspace_name].tables[self.function_table_name].views)
self.assertNotIn("mv1", self.cluster.metadata.keyspaces[self.keyspace_name].views)
self.assertDictEqual({}, self.cluster.metadata.keyspaces[self.keyspace_name].tables[self.function_table_name].views)
self.assertDictEqual({}, self.cluster.metadata.keyspaces[self.keyspace_name].views)
self.session.execute("CREATE MATERIALIZED VIEW {0}.mv1 AS SELECT c FROM {0}.{1} WHERE c IS NOT NULL PRIMARY KEY (pk, c)".format(self.keyspace_name, self.function_table_name))
class MaterializedViewMetadataTestComplex(BasicSegregatedKeyspaceUnitTestCase):
def setUp(self):
if CASS_SERVER_VERSION < (3, 0):
raise unittest.SkipTest("Materialized views require Cassandra 3.0+")
super(MaterializedViewMetadataTestComplex, self).setUp()
def test_create_view_metadata(self):
"""
@@ -2016,7 +2011,7 @@ class MaterializedViewMetadataTest(unittest.TestCase):
day INT,
score INT,
PRIMARY KEY (user, game, year, month, day)
)""".format(self.ksname)
)""".format(self.keyspace_name)
self.session.execute(create_table)
@@ -2024,11 +2019,11 @@ class MaterializedViewMetadataTest(unittest.TestCase):
SELECT game, year, month, score, user, day FROM {0}.scores
WHERE game IS NOT NULL AND year IS NOT NULL AND month IS NOT NULL AND score IS NOT NULL AND user IS NOT NULL AND day IS NOT NULL
PRIMARY KEY ((game, year, month), score, user, day)
WITH CLUSTERING ORDER BY (score DESC, user ASC, day ASC)""".format(self.ksname)
WITH CLUSTERING ORDER BY (score DESC, user ASC, day ASC)""".format(self.keyspace_name)
self.session.execute(create_mv)
score_table = self.cluster.metadata.keyspaces[self.ksname].tables['scores']
mv = self.cluster.metadata.keyspaces[self.ksname].views['monthlyhigh']
score_table = self.cluster.metadata.keyspaces[self.keyspace_name].tables['scores']
mv = self.cluster.metadata.keyspaces[self.keyspace_name].views['monthlyhigh']
self.assertIsNotNone(score_table.views["monthlyhigh"])
self.assertIsNotNone(len(score_table.views), 1)
@@ -2056,7 +2051,7 @@ class MaterializedViewMetadataTest(unittest.TestCase):
self.assertIsNotNone(score_table.columns['score'])
# Validate basic mv information
self.assertEquals(mv.keyspace_name, self.ksname)
self.assertEquals(mv.keyspace_name, self.keyspace_name)
self.assertEquals(mv.name, "monthlyhigh")
self.assertEquals(mv.base_table_name, "scores")
self.assertFalse(mv.include_all_columns)
@@ -2110,7 +2105,7 @@ class MaterializedViewMetadataTest(unittest.TestCase):
self.assertEquals(day_column.is_static, mv.clustering_key[2].is_static)
self.assertEquals(day_column.is_reversed, mv.clustering_key[2].is_reversed)
def test_create_mv_changes(self):
def test_base_table_mv_changes(self):
"""
test to ensure that materialized view metadata is properly updated with base table changes
@@ -2132,39 +2127,53 @@ class MaterializedViewMetadataTest(unittest.TestCase):
day INT,
score TEXT,
PRIMARY KEY (user, game, year, month, day)
)""".format(self.ksname)
)""".format(self.keyspace_name)
self.session.execute(create_table)
view_name = 'monthlyhigh'
create_mv = """CREATE MATERIALIZED VIEW {0}.{1} AS
create_mv = """CREATE MATERIALIZED VIEW {0}.monthlyhigh AS
SELECT game, year, month, score, user, day FROM {0}.scores
WHERE game IS NOT NULL AND year IS NOT NULL AND month IS NOT NULL AND score IS NOT NULL AND user IS NOT NULL AND day IS NOT NULL
PRIMARY KEY ((game, year, month), score, user, day)
WITH CLUSTERING ORDER BY (score DESC, user ASC, day ASC)""".format(self.ksname, view_name)
WITH CLUSTERING ORDER BY (score DESC, user ASC, day ASC)""".format(self.keyspace_name)
create_mv_alltime = """CREATE MATERIALIZED VIEW {0}.alltimehigh AS
SELECT * FROM {0}.scores
WHERE game IS NOT NULL AND score IS NOT NULL AND user IS NOT NULL AND year IS NOT NULL AND month IS NOT NULL AND day IS NOT NULL
PRIMARY KEY (game, score, user, year, month, day)
WITH CLUSTERING ORDER BY (score DESC)""".format(self.keyspace_name)
self.session.execute(create_mv)
score_table = self.cluster.metadata.keyspaces[self.ksname].tables['scores']
self.assertIn(view_name, score_table.views)
self.assertIn(view_name, self.cluster.metadata.keyspaces[self.ksname].views)
self.session.execute(create_mv_alltime)
insert_fouls = """ALTER TABLE {0}.scores ADD fouls INT""".format(self.ksname)
score_table = self.cluster.metadata.keyspaces[self.keyspace_name].tables['scores']
self.assertIsNotNone(score_table.views["monthlyhigh"])
self.assertEqual(len(self.cluster.metadata.keyspaces[self.keyspace_name].views), 2)
insert_fouls = """ALTER TABLE {0}.scores ADD fouls INT""".format((self.keyspace_name))
self.session.execute(insert_fouls)
self.assertIn(view_name, self.cluster.metadata.keyspaces[self.ksname].views)
self.assertEqual(len(self.cluster.metadata.keyspaces[self.keyspace_name].views), 2)
alter_scores = """ALTER TABLE {0}.scores ALTER score TYPE blob""".format(self.ksname)
alter_scores = """ALTER TABLE {0}.scores ALTER score blob""".format((self.keyspace_name))
self.session.execute(alter_scores) # ERROR https://issues.apache.org/jira/browse/CASSANDRA-10424
self.assertIn(view_name, self.cluster.metadata.keyspaces[self.ksname].views)
self.session.execute(alter_scores)
self.assertEqual(len(self.cluster.metadata.keyspaces[self.keyspace_name].views), 2)
score_column = self.cluster.metadata.keyspaces[self.ksname].tables['scores'].columns['score']
score_column = self.cluster.metadata.keyspaces[self.keyspace_name].tables['scores'].columns['score']
self.assertEquals(score_column.typestring, 'blob')
score_mv_column = self.cluster.metadata.keyspaces[self.ksname].views["monthlyhigh"].columns['score']
score_mv_column = self.cluster.metadata.keyspaces[self.keyspace_name].views["monthlyhigh"].columns['score']
self.assertEquals(score_mv_column.typestring, 'blob')
mv_alltime = self.cluster.metadata.keyspaces[self.keyspace_name].views["alltimehigh"]
self.assertIn("fouls", mv_alltime.columns)
mv_alltime_fouls_comumn = self.cluster.metadata.keyspaces[self.keyspace_name].views["alltimehigh"].columns['fouls']
self.assertEquals(mv_alltime_fouls_comumn.typestring, 'int')
def test_metadata_with_quoted_identifiers(self):
"""
test to ensure that materialized view metadata is properly constructed when quoted identifiers are used
@@ -2184,7 +2193,7 @@ class MaterializedViewMetadataTest(unittest.TestCase):
"theKey" int,
"the;Clustering" int,
"the Value" int,
PRIMARY KEY ("theKey", "the;Clustering"))""".format(self.ksname)
PRIMARY KEY ("theKey", "the;Clustering"))""".format(self.keyspace_name)
self.session.execute(create_table)
@@ -2192,12 +2201,12 @@ class MaterializedViewMetadataTest(unittest.TestCase):
SELECT "theKey", "the;Clustering", "the Value"
FROM {0}.t1
WHERE "theKey" IS NOT NULL AND "the;Clustering" IS NOT NULL AND "the Value" IS NOT NULL
PRIMARY KEY ("theKey", "the;Clustering")""".format(self.ksname)
PRIMARY KEY ("theKey", "the;Clustering")""".format(self.keyspace_name)
self.session.execute(create_mv)
t1_table = self.cluster.metadata.keyspaces[self.ksname].tables['t1']
mv = self.cluster.metadata.keyspaces[self.ksname].views['mv1']
t1_table = self.cluster.metadata.keyspaces[self.keyspace_name].tables['t1']
mv = self.cluster.metadata.keyspaces[self.keyspace_name].views['mv1']
self.assertIsNotNone(t1_table.views["mv1"])
self.assertIsNotNone(len(t1_table.views), 1)
@@ -2216,7 +2225,7 @@ class MaterializedViewMetadataTest(unittest.TestCase):
self.assertIsNotNone(t1_table.columns['the Value'])
# Validate basic mv information
self.assertEquals(mv.keyspace_name, self.ksname)
self.assertEquals(mv.keyspace_name, self.keyspace_name)
self.assertEquals(mv.name, "mv1")
self.assertEquals(mv.base_table_name, "t1")
self.assertFalse(mv.include_all_columns)

View File

@@ -26,13 +26,15 @@ from cassandra.query import (PreparedStatement, BoundStatement, SimpleStatement,
from cassandra.cluster import Cluster
from cassandra.policies import HostDistance
from tests.integration import use_singledc, PROTOCOL_VERSION
from tests.integration import use_singledc, PROTOCOL_VERSION, BasicSharedKeyspaceUnitTestCase, get_server_versions
import re
def setup_module():
use_singledc()
global CASS_SERVER_VERSION
CASS_SERVER_VERSION = get_server_versions()[0]
class QueryTests(unittest.TestCase):
@@ -617,3 +619,163 @@ class BatchStatementDefaultRoutingKeyTests(unittest.TestCase):
self.assertIsNotNone(batch.routing_key)
self.assertEqual(batch.routing_key, self.prepared.bind((1, 0)).routing_key)
class MaterializedViewQueryTest(BasicSharedKeyspaceUnitTestCase):
def setUp(self):
if CASS_SERVER_VERSION < (3, 0):
raise unittest.SkipTest("Materialized views require Cassandra 3.0+")
def test_mv_filtering(self):
"""
Test to ensure that cql filtering where clauses are properly supported in the python driver.
test_mv_filtering Tests that various complex MV where clauses produce the correct results. It also validates that
these results and the grammar is supported appropriately.
@since 3.0.0
@jira_ticket PYTHON-399
@expected_result Materialized view where clauses should produce the appropriate results.
@test_category materialized_view
"""
create_table = """CREATE TABLE {0}.scores(
user TEXT,
game TEXT,
year INT,
month INT,
day INT,
score INT,
PRIMARY KEY (user, game, year, month, day)
)""".format(self.ksname)
self.session.execute(create_table)
create_mv_alltime = """CREATE MATERIALIZED VIEW {0}.alltimehigh AS
SELECT * FROM {0}.scores
WHERE game IS NOT NULL AND score IS NOT NULL AND user IS NOT NULL AND year IS NOT NULL AND month IS NOT NULL AND day IS NOT NULL
PRIMARY KEY (game, score, user, year, month, day)
WITH CLUSTERING ORDER BY (score DESC)""".format(self.ksname)
create_mv_dailyhigh = """CREATE MATERIALIZED VIEW {0}.dailyhigh AS
SELECT * FROM {0}.scores
WHERE game IS NOT NULL AND year IS NOT NULL AND month IS NOT NULL AND day IS NOT NULL AND score IS NOT NULL AND user IS NOT NULL
PRIMARY KEY ((game, year, month, day), score, user)
WITH CLUSTERING ORDER BY (score DESC)""".format(self.ksname)
create_mv_monthlyhigh = """CREATE MATERIALIZED VIEW {0}.monthlyhigh AS
SELECT * FROM {0}.scores
WHERE game IS NOT NULL AND year IS NOT NULL AND month IS NOT NULL AND score IS NOT NULL AND user IS NOT NULL AND day IS NOT NULL
PRIMARY KEY ((game, year, month), score, user, day)
WITH CLUSTERING ORDER BY (score DESC)""".format(self.ksname)
create_mv_filtereduserhigh = """CREATE MATERIALIZED VIEW {0}.filtereduserhigh AS
SELECT * FROM {0}.scores
WHERE user in ('jbellis', 'pcmanus') AND game IS NOT NULL AND score IS NOT NULL AND year is NOT NULL AND day is not NULL and month IS NOT NULL
PRIMARY KEY (game, score, user, year, month, day)
WITH CLUSTERING ORDER BY (score DESC)""".format(self.ksname)
self.session.execute(create_mv_alltime)
self.session.execute(create_mv_dailyhigh)
self.session.execute(create_mv_monthlyhigh)
self.session.execute(create_mv_filtereduserhigh)
prepared_insert = self.session.prepare("""INSERT INTO {0}.scores (user, game, year, month, day, score) VALUES (?, ?, ? ,? ,?, ?)""".format(self.ksname))
bound = prepared_insert.bind(('pcmanus', 'Coup', 2015, 5, 1, 4000))
self.session.execute(bound)
bound = prepared_insert.bind(('jbellis', 'Coup', 2015, 5, 3, 1750))
self.session.execute(bound)
bound = prepared_insert.bind(('yukim', 'Coup', 2015, 5, 3, 2250))
self.session.execute(bound)
bound = prepared_insert.bind(('tjake', 'Coup', 2015, 5, 3, 500))
self.session.execute(bound)
bound = prepared_insert.bind(('iamaleksey', 'Coup', 2015, 6, 1, 2500))
self.session.execute(bound)
bound = prepared_insert.bind(('tjake', 'Coup', 2015, 6, 2, 1000))
self.session.execute(bound)
bound = prepared_insert.bind(('pcmanus', 'Coup', 2015, 6, 2, 2000))
self.session.execute(bound)
bound = prepared_insert.bind(('jmckenzie', 'Coup', 2015, 6, 9, 2700))
self.session.execute(bound)
bound = prepared_insert.bind(('jbellis', 'Coup', 2015, 6, 20, 3500))
self.session.execute(bound)
bound = prepared_insert.bind(('jbellis', 'Checkers', 2015, 6, 20, 1200))
self.session.execute(bound)
bound = prepared_insert.bind(('jbellis', 'Chess', 2015, 6, 21, 3500))
self.session.execute(bound)
bound = prepared_insert.bind(('pcmanus', 'Chess', 2015, 1, 25, 3200))
self.session.execute(bound)
# Test simple statement and alltime high filtering
query_statement = SimpleStatement("SELECT * FROM {0}.alltimehigh WHERE game='Coup'".format(self.ksname),
consistency_level=ConsistencyLevel.QUORUM)
results = self.session.execute(query_statement)
self.assertEquals(results[0].game, 'Coup')
self.assertEquals(results[0].year, 2015)
self.assertEquals(results[0].month, 5)
self.assertEquals(results[0].day, 1)
self.assertEquals(results[0].score, 4000)
self.assertEquals(results[0].user, "pcmanus")
# Test prepared statement and daily high filtering
prepared_query = self.session.prepare("SELECT * FROM {0}.dailyhigh WHERE game=? AND year=? AND month=? and day=?".format(self.ksname).format(self.ksname))
bound_query = prepared_query.bind(("Coup", 2015, 6, 2))
results = self.session.execute(bound_query)
self.assertEquals(results[0].game, 'Coup')
self.assertEquals(results[0].year, 2015)
self.assertEquals(results[0].month, 6)
self.assertEquals(results[0].day, 2)
self.assertEquals(results[0].score, 2000)
self.assertEquals(results[0].user, "pcmanus")
self.assertEquals(results[1].game, 'Coup')
self.assertEquals(results[1].year, 2015)
self.assertEquals(results[1].month, 6)
self.assertEquals(results[1].day, 2)
self.assertEquals(results[1].score, 1000)
self.assertEquals(results[1].user, "tjake")
# Test montly high range queries
prepared_query = self.session.prepare("SELECT * FROM {0}.monthlyhigh WHERE game=? AND year=? AND month=? and score >= ? and score <= ?".format(self.ksname).format(self.ksname))
bound_query = prepared_query.bind(("Coup", 2015, 6, 2500, 3500))
results = self.session.execute(bound_query)
self.assertEquals(results[0].game, 'Coup')
self.assertEquals(results[0].year, 2015)
self.assertEquals(results[0].month, 6)
self.assertEquals(results[0].day, 20)
self.assertEquals(results[0].score, 3500)
self.assertEquals(results[0].user, "jbellis")
self.assertEquals(results[1].game, 'Coup')
self.assertEquals(results[1].year, 2015)
self.assertEquals(results[1].month, 6)
self.assertEquals(results[1].day, 9)
self.assertEquals(results[1].score, 2700)
self.assertEquals(results[1].user, "jmckenzie")
self.assertEquals(results[2].game, 'Coup')
self.assertEquals(results[2].year, 2015)
self.assertEquals(results[2].month, 6)
self.assertEquals(results[2].day, 1)
self.assertEquals(results[2].score, 2500)
self.assertEquals(results[2].user, "iamaleksey")
# Test filtered user high scores
query_statement = SimpleStatement("SELECT * FROM {0}.filtereduserhigh WHERE game='Chess'".format(self.ksname),
consistency_level=ConsistencyLevel.QUORUM)
results = self.session.execute(query_statement)
self.assertEquals(results[0].game, 'Chess')
self.assertEquals(results[0].year, 2015)
self.assertEquals(results[0].month, 6)
self.assertEquals(results[0].day, 21)
self.assertEquals(results[0].score, 3500)
self.assertEquals(results[0].user, "jbellis")
self.assertEquals(results[1].game, 'Chess')
self.assertEquals(results[1].year, 2015)
self.assertEquals(results[1].month, 1)
self.assertEquals(results[1].day, 25)
self.assertEquals(results[1].score, 3200)
self.assertEquals(results[1].user, "pcmanus")

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from tests.integration import get_server_versions, use_singledc, PROTOCOL_VERSION
from tests.integration import get_server_versions, use_singledc, PROTOCOL_VERSION, BasicSharedKeyspaceUnitTestCaseWFunctionTable
try:
import unittest2 as unittest
@@ -28,45 +28,37 @@ def setup_module():
use_singledc()
class RowFactoryTests(unittest.TestCase):
class RowFactoryTests(BasicSharedKeyspaceUnitTestCaseWFunctionTable):
"""
Test different row_factories and access code
"""
def setUp(self):
self.cluster = Cluster(protocol_version=PROTOCOL_VERSION)
self.session = self.cluster.connect()
def tearDown(self):
self.cluster.shutdown()
truncate = '''
TRUNCATE test3rf.test
'''
insert1 = '''
INSERT INTO test3rf.test
super(RowFactoryTests, self).setUp()
self.insert1 = '''
INSERT INTO {0}.{1}
( k , v )
VALUES
( 1 , 1 )
'''
'''.format(self.keyspace_name, self.function_table_name)
insert2 = '''
INSERT INTO test3rf.test
self.insert2 = '''
INSERT INTO {0}.{1}
( k , v )
VALUES
( 2 , 2 )
'''
'''.format(self.keyspace_name, self.function_table_name)
select = '''
SELECT * FROM test3rf.test
'''
self.select = '''
SELECT * FROM {0}.{1}
'''.format(self.keyspace_name, self.function_table_name)
def tearDown(self):
self.drop_function_table()
def test_tuple_factory(self):
session = self.session
session.row_factory = tuple_factory
session.execute(self.truncate)
session.execute(self.insert1)
session.execute(self.insert2)
@@ -87,7 +79,6 @@ class RowFactoryTests(unittest.TestCase):
session = self.session
session.row_factory = named_tuple_factory
session.execute(self.truncate)
session.execute(self.insert1)
session.execute(self.insert2)
@@ -107,7 +98,6 @@ class RowFactoryTests(unittest.TestCase):
session = self.session
session.row_factory = dict_factory
session.execute(self.truncate)
session.execute(self.insert1)
session.execute(self.insert2)
@@ -128,7 +118,6 @@ class RowFactoryTests(unittest.TestCase):
session = self.session
session.row_factory = ordered_dict_factory
session.execute(self.truncate)
session.execute(self.insert1)
session.execute(self.insert2)
@@ -154,7 +143,6 @@ class NamedTupleFactoryAndNumericColNamesTests(unittest.TestCase):
def setup_class(cls):
cls.cluster = Cluster(protocol_version=PROTOCOL_VERSION)
cls.session = cls.cluster.connect()
cls._cass_version, cls._cql_version = get_server_versions()
ddl = '''
CREATE TABLE test1rf.table_num_col ( key blob PRIMARY KEY, "626972746864617465" blob )