|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
15 | | -from cassandra.cqlengine import operators |
| 15 | +from cassandra.cqlengine import operators, connection |
16 | 16 | from cassandra.cqlengine.named import NamedKeyspace |
17 | 17 | from cassandra.cqlengine.operators import EqualsOperator, GreaterThanOrEqualOperator |
18 | 18 | from cassandra.cqlengine.query import ResultObject |
| 19 | +from cassandra.concurrent import execute_concurrent_with_args |
19 | 20 |
|
20 | 21 | from tests.integration.cqlengine.base import BaseCassEngTestCase |
21 | 22 | from tests.integration.cqlengine.query.test_queryset import BaseQuerySetUsage |
22 | 23 |
|
23 | 24 |
|
| 25 | +from tests.integration import BasicSharedKeyspaceUnitTestCase |
| 26 | + |
| 27 | + |
24 | 28 | class TestQuerySetOperation(BaseCassEngTestCase): |
25 | 29 |
|
26 | 30 | @classmethod |
@@ -259,3 +263,84 @@ def test_get_multipleobjects_exception(self): |
259 | 263 | self.table.objects.get(test_id=1) |
260 | 264 |
|
261 | 265 |
|
| 266 | +class TestQuerySetCountSelectionAndIteration(BasicSharedKeyspaceUnitTestCase): |
| 267 | + |
| 268 | + def test_named_table_with_mv(self): |
| 269 | + """ |
| 270 | + Test NamedTable access to materialized views |
| 271 | +
|
| 272 | + Creates some materialized views using Traditional CQL. Then ensures we can access those materialized view using |
| 273 | + the NamedKeyspace, and NamedTable interfaces. Tests basic filtering as well. |
| 274 | +
|
| 275 | + @since 3.0.0 |
| 276 | + @jira_ticket PYTHON-406 |
| 277 | + @expected_result Named Tables should have access to materialized views |
| 278 | +
|
| 279 | + @test_category materialized_view |
| 280 | + """ |
| 281 | + connection.setup(['127.0.0.1'], self.keyspace_name) |
| 282 | + |
| 283 | + # Create a base table and two materialized views |
| 284 | + create_table = """CREATE TABLE {0}.scores( |
| 285 | + user TEXT, |
| 286 | + game TEXT, |
| 287 | + year INT, |
| 288 | + month INT, |
| 289 | + day INT, |
| 290 | + score INT, |
| 291 | + PRIMARY KEY (user, game, year, month, day) |
| 292 | + )""".format(self.keyspace_name) |
| 293 | + |
| 294 | + self.session.execute(create_table) |
| 295 | + create_mv = """CREATE MATERIALIZED VIEW {0}.monthlyhigh AS |
| 296 | + SELECT game, year, month, score, user, day FROM {0}.scores |
| 297 | + 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 |
| 298 | + PRIMARY KEY ((game, year, month), score, user, day) |
| 299 | + WITH CLUSTERING ORDER BY (score DESC, user ASC, day ASC)""".format(self.keyspace_name) |
| 300 | + |
| 301 | + self.session.execute(create_mv) |
| 302 | + |
| 303 | + create_mv_alltime = """CREATE MATERIALIZED VIEW {0}.alltimehigh AS |
| 304 | + SELECT * FROM {0}.scores |
| 305 | + 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 |
| 306 | + PRIMARY KEY (game, score, user, year, month, day) |
| 307 | + WITH CLUSTERING ORDER BY (score DESC)""".format(self.keyspace_name) |
| 308 | + |
| 309 | + self.session.execute(create_mv_alltime) |
| 310 | + |
| 311 | + # Populate the base table with data |
| 312 | + prepared_insert = self.session.prepare("""INSERT INTO {0}.scores (user, game, year, month, day, score) VALUES (?, ?, ? ,? ,?, ?)""".format(self.keyspace_name)) |
| 313 | + parameters = {('pcmanus', 'Coup', 2015, 5, 1, 4000), |
| 314 | + ('jbellis', 'Coup', 2015, 5, 3, 1750), |
| 315 | + ('yukim', 'Coup', 2015, 5, 3, 2250), |
| 316 | + ('tjake', 'Coup', 2015, 5, 3, 500), |
| 317 | + ('iamaleksey', 'Coup', 2015, 6, 1, 2500), |
| 318 | + ('tjake', 'Coup', 2015, 6, 2, 1000), |
| 319 | + ('pcmanus', 'Coup', 2015, 6, 2, 2000), |
| 320 | + ('jmckenzie', 'Coup', 2015, 6, 9, 2700), |
| 321 | + ('jbellis', 'Coup', 2015, 6, 20, 3500), |
| 322 | + ('jbellis', 'Checkers', 2015, 6, 20, 1200), |
| 323 | + ('jbellis', 'Chess', 2015, 6, 21, 3500), |
| 324 | + ('pcmanus', 'Chess', 2015, 1, 25, 3200)} |
| 325 | + execute_concurrent_with_args(self.session, prepared_insert, parameters) |
| 326 | + |
| 327 | + # Attempt to query the data using Named Table interface |
| 328 | + # Also test filtering on mv's |
| 329 | + key_space = NamedKeyspace(self.keyspace_name) |
| 330 | + table = key_space.table("scores") |
| 331 | + mv_monthly = key_space.table("monthlyhigh") |
| 332 | + table_objects = table.objects.all() |
| 333 | + mv_monthly_objects = mv_monthly.objects.all() |
| 334 | + mv_all_time = key_space.table("alltimehigh") |
| 335 | + mv_all_objects = mv_all_time.objects.all() |
| 336 | + self.assertEqual(len(table_objects), len(parameters)) |
| 337 | + self.assertEqual(len(mv_monthly_objects), len(parameters)) |
| 338 | + self.assertEqual(len(mv_all_objects), len(parameters)) |
| 339 | + |
| 340 | + filtered_mv_monthly_objects = mv_monthly.objects.filter(game='Chess', year=2015, month=6) |
| 341 | + self.assertEquals(len(filtered_mv_monthly_objects), 1) |
| 342 | + self.assertEquals(filtered_mv_monthly_objects[0]['score'], 3500) |
| 343 | + self.assertEquals(filtered_mv_monthly_objects[0]['user'], 'jbellis') |
| 344 | + filtered_mv_alltime_objects = mv_all_time.objects.filter(game='Chess') |
| 345 | + self.assertEquals(len(filtered_mv_alltime_objects), 2) |
| 346 | + self.assertEquals(filtered_mv_alltime_objects[0]['score'], 3500) |
0 commit comments