317 lines
10 KiB
Python
317 lines
10 KiB
Python
# Copyright 2013-2016 DataStax, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
try:
|
|
import unittest2 as unittest
|
|
except ImportError:
|
|
import unittest # noqa
|
|
|
|
import mock
|
|
from uuid import uuid4
|
|
|
|
from cassandra.cqlengine import columns
|
|
from cassandra.cqlengine.management import sync_table, drop_table
|
|
from cassandra.cqlengine.models import Model
|
|
from cassandra.cqlengine.query import BatchQuery, BatchType, LWTException, IfExistsWithCounterColumn
|
|
|
|
from tests.integration.cqlengine.base import BaseCassEngTestCase
|
|
from tests.integration import PROTOCOL_VERSION
|
|
|
|
|
|
class TestIfExistsModel(Model):
|
|
|
|
id = columns.UUID(primary_key=True, default=lambda: uuid4())
|
|
count = columns.Integer()
|
|
text = columns.Text(required=False)
|
|
|
|
|
|
class TestIfExistsModel2(Model):
|
|
|
|
id = columns.Integer(primary_key=True)
|
|
count = columns.Integer(primary_key=True, required=False)
|
|
text = columns.Text(required=False)
|
|
|
|
|
|
class TestIfExistsWithCounterModel(Model):
|
|
|
|
id = columns.UUID(primary_key=True, default=lambda: uuid4())
|
|
likes = columns.Counter()
|
|
|
|
|
|
class BaseIfExistsTest(BaseCassEngTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(BaseIfExistsTest, cls).setUpClass()
|
|
sync_table(TestIfExistsModel)
|
|
sync_table(TestIfExistsModel2)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
super(BaseIfExistsTest, cls).tearDownClass()
|
|
drop_table(TestIfExistsModel)
|
|
drop_table(TestIfExistsModel2)
|
|
|
|
|
|
class BaseIfExistsWithCounterTest(BaseCassEngTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(BaseIfExistsWithCounterTest, cls).setUpClass()
|
|
sync_table(TestIfExistsWithCounterModel)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
super(BaseIfExistsWithCounterTest, cls).tearDownClass()
|
|
drop_table(TestIfExistsWithCounterModel)
|
|
|
|
|
|
class IfExistsUpdateTests(BaseIfExistsTest):
|
|
|
|
@unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0")
|
|
def test_update_if_exists(self):
|
|
"""
|
|
Tests that update with if_exists work as expected
|
|
|
|
@since 3.1
|
|
@jira_ticket PYTHON-432
|
|
@expected_result updates to be applied when primary key exists, otherwise LWT exception to be thrown
|
|
|
|
@test_category object_mapper
|
|
"""
|
|
|
|
id = uuid4()
|
|
|
|
m = TestIfExistsModel.create(id=id, count=8, text='123456789')
|
|
m.text = 'changed'
|
|
m.if_exists().update()
|
|
m = TestIfExistsModel.get(id=id)
|
|
self.assertEqual(m.text, 'changed')
|
|
|
|
# save()
|
|
m.text = 'changed_again'
|
|
m.if_exists().save()
|
|
m = TestIfExistsModel.get(id=id)
|
|
self.assertEqual(m.text, 'changed_again')
|
|
|
|
m = TestIfExistsModel(id=uuid4(), count=44) # do not exists
|
|
with self.assertRaises(LWTException) as assertion:
|
|
m.if_exists().update()
|
|
|
|
self.assertEqual(assertion.exception.existing, {
|
|
'[applied]': False,
|
|
})
|
|
|
|
# queryset update
|
|
with self.assertRaises(LWTException) as assertion:
|
|
TestIfExistsModel.objects(id=uuid4()).if_exists().update(count=8)
|
|
|
|
self.assertEqual(assertion.exception.existing, {
|
|
'[applied]': False,
|
|
})
|
|
|
|
@unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0")
|
|
def test_batch_update_if_exists_success(self):
|
|
"""
|
|
Tests that batch update with if_exists work as expected
|
|
|
|
@since 3.1
|
|
@jira_ticket PYTHON-432
|
|
@expected_result
|
|
|
|
@test_category object_mapper
|
|
"""
|
|
|
|
id = uuid4()
|
|
|
|
m = TestIfExistsModel.create(id=id, count=8, text='123456789')
|
|
|
|
with BatchQuery() as b:
|
|
m.text = '111111111'
|
|
m.batch(b).if_exists().update()
|
|
|
|
with self.assertRaises(LWTException) as assertion:
|
|
with BatchQuery() as b:
|
|
m = TestIfExistsModel(id=uuid4(), count=42) # Doesn't exist
|
|
m.batch(b).if_exists().update()
|
|
|
|
self.assertEqual(assertion.exception.existing, {
|
|
'[applied]': False,
|
|
})
|
|
|
|
q = TestIfExistsModel.objects(id=id)
|
|
self.assertEqual(len(q), 1)
|
|
|
|
tm = q.first()
|
|
self.assertEqual(tm.count, 8)
|
|
self.assertEqual(tm.text, '111111111')
|
|
|
|
@unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0")
|
|
def test_batch_mixed_update_if_exists_success(self):
|
|
"""
|
|
Tests that batch update with with one bad query will still fail with LWTException
|
|
|
|
@since 3.1
|
|
@jira_ticket PYTHON-432
|
|
@expected_result
|
|
|
|
@test_category object_mapper
|
|
"""
|
|
|
|
m = TestIfExistsModel2.create(id=1, count=8, text='123456789')
|
|
with self.assertRaises(LWTException) as assertion:
|
|
with BatchQuery() as b:
|
|
m.text = '111111112'
|
|
m.batch(b).if_exists().update() # Does exist
|
|
n = TestIfExistsModel2(id=1, count=10, text="Failure") # Doesn't exist
|
|
n.batch(b).if_exists().update()
|
|
|
|
self.assertEqual(assertion.exception.existing.get('[applied]'), False)
|
|
|
|
@unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0")
|
|
def test_delete_if_exists(self):
|
|
"""
|
|
Tests that delete with if_exists work, and throw proper LWT exception when they are are not applied
|
|
|
|
@since 3.1
|
|
@jira_ticket PYTHON-432
|
|
@expected_result Deletes will be preformed if they exist, otherwise throw LWT exception
|
|
|
|
@test_category object_mapper
|
|
"""
|
|
|
|
id = uuid4()
|
|
|
|
m = TestIfExistsModel.create(id=id, count=8, text='123456789')
|
|
m.if_exists().delete()
|
|
q = TestIfExistsModel.objects(id=id)
|
|
self.assertEqual(len(q), 0)
|
|
|
|
m = TestIfExistsModel(id=uuid4(), count=44) # do not exists
|
|
with self.assertRaises(LWTException) as assertion:
|
|
m.if_exists().delete()
|
|
|
|
self.assertEqual(assertion.exception.existing, {
|
|
'[applied]': False,
|
|
})
|
|
|
|
# queryset delete
|
|
with self.assertRaises(LWTException) as assertion:
|
|
TestIfExistsModel.objects(id=uuid4()).if_exists().delete()
|
|
|
|
self.assertEqual(assertion.exception.existing, {
|
|
'[applied]': False,
|
|
})
|
|
|
|
@unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0")
|
|
def test_batch_delete_if_exists_success(self):
|
|
"""
|
|
Tests that batch deletes with if_exists work, and throw proper LWTException when they are are not applied
|
|
|
|
@since 3.1
|
|
@jira_ticket PYTHON-432
|
|
@expected_result Deletes will be preformed if they exist, otherwise throw LWTException
|
|
|
|
@test_category object_mapper
|
|
"""
|
|
|
|
id = uuid4()
|
|
|
|
m = TestIfExistsModel.create(id=id, count=8, text='123456789')
|
|
|
|
with BatchQuery() as b:
|
|
m.batch(b).if_exists().delete()
|
|
|
|
q = TestIfExistsModel.objects(id=id)
|
|
self.assertEqual(len(q), 0)
|
|
|
|
with self.assertRaises(LWTException) as assertion:
|
|
with BatchQuery() as b:
|
|
m = TestIfExistsModel(id=uuid4(), count=42) # Doesn't exist
|
|
m.batch(b).if_exists().delete()
|
|
|
|
self.assertEqual(assertion.exception.existing, {
|
|
'[applied]': False,
|
|
})
|
|
|
|
@unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0")
|
|
def test_batch_delete_mixed(self):
|
|
"""
|
|
Tests that batch deletes with multiple queries and throw proper LWTException when they are are not all applicable
|
|
|
|
@since 3.1
|
|
@jira_ticket PYTHON-432
|
|
@expected_result If one delete clause doesn't exist all should fail.
|
|
|
|
@test_category object_mapper
|
|
"""
|
|
|
|
m = TestIfExistsModel2.create(id=3, count=8, text='123456789')
|
|
|
|
with self.assertRaises(LWTException) as assertion:
|
|
with BatchQuery() as b:
|
|
m.batch(b).if_exists().delete() # Does exist
|
|
n = TestIfExistsModel2(id=3, count=42, text='1111111') # Doesn't exist
|
|
n.batch(b).if_exists().delete()
|
|
|
|
self.assertEqual(assertion.exception.existing.get('[applied]'), False)
|
|
q = TestIfExistsModel2.objects(id=3, count=8)
|
|
self.assertEqual(len(q), 1)
|
|
|
|
|
|
class IfExistsQueryTest(BaseIfExistsTest):
|
|
|
|
def test_if_exists_included_on_queryset_update(self):
|
|
|
|
with mock.patch.object(self.session, 'execute') as m:
|
|
TestIfExistsModel.objects(id=uuid4()).if_exists().update(count=42)
|
|
|
|
query = m.call_args[0][0].query_string
|
|
self.assertIn("IF EXISTS", query)
|
|
|
|
def test_if_exists_included_on_update(self):
|
|
""" tests that if_exists on models update works as expected """
|
|
|
|
with mock.patch.object(self.session, 'execute') as m:
|
|
TestIfExistsModel(id=uuid4()).if_exists().update(count=8)
|
|
|
|
query = m.call_args[0][0].query_string
|
|
self.assertIn("IF EXISTS", query)
|
|
|
|
def test_if_exists_included_on_delete(self):
|
|
""" tests that if_exists on models delete works as expected """
|
|
|
|
with mock.patch.object(self.session, 'execute') as m:
|
|
TestIfExistsModel(id=uuid4()).if_exists().delete()
|
|
|
|
query = m.call_args[0][0].query_string
|
|
self.assertIn("IF EXISTS", query)
|
|
|
|
|
|
class IfExistWithCounterTest(BaseIfExistsWithCounterTest):
|
|
|
|
def test_instance_raise_exception(self):
|
|
"""
|
|
Tests if exists is used with a counter column model that exception are thrown
|
|
|
|
@since 3.1
|
|
@jira_ticket PYTHON-432
|
|
@expected_result Deletes will be preformed if they exist, otherwise throw LWTException
|
|
|
|
@test_category object_mapper
|
|
"""
|
|
id = uuid4()
|
|
with self.assertRaises(IfExistsWithCounterColumn):
|
|
TestIfExistsWithCounterModel.if_exists()
|
|
|