- merge rbbd81cb9a341 from 0.6 branch

This commit is contained in:
Mike Bayer
2010-12-15 16:30:41 -05:00
parent 1f0e7a6120
commit 80ae02f7dc
3 changed files with 188 additions and 7 deletions
+6
View File
@@ -14,6 +14,12 @@ CHANGES
that weren't previously saved in the "mutable changes"
dictionary.
- Fixed uow bug whereby expired objects passed to
Session.delete() would not have unloaded references
or collections taken into account when deleting
objects, despite passive_deletes remaining at
its default of False. [ticket:2002]
- "innerjoin" flag doesn't take effect along the chain
of joinedload() joins if a previous join in that chain
is an outer join, thus allowing primary rows without
+3 -1
View File
@@ -221,6 +221,8 @@ class DependencyProcessor(object):
pass
def prop_has_changes(self, uowcommit, states, isdelete):
passive = not isdelete or self.passive_deletes
for s in states:
# TODO: add a high speed method
# to InstanceState which returns: attribute
@@ -228,7 +230,7 @@ class DependencyProcessor(object):
history = uowcommit.get_attribute_history(
s,
self.key,
passive=True)
passive=passive)
if history and not history.empty():
return True
else:
+179 -6
View File
@@ -223,6 +223,74 @@ class RudimentaryFlushTest(UOWTest):
{'id':u1.id}
),
)
def test_many_to_one_delete_unloaded(self):
mapper(User, users)
mapper(Address, addresses, properties={
'parent':relationship(User)
})
parent = User(name='p1')
c1, c2 = Address(email_address='c1', parent=parent), \
Address(email_address='c2', parent=parent)
session = Session()
session.add_all([c1, c2])
session.add(parent)
session.flush()
pid = parent.id
c1id = c1.id
c2id = c2.id
session.expire(parent)
session.expire(c1)
session.expire(c2)
session.delete(c1)
session.delete(c2)
session.delete(parent)
# testing that relationships
# are loaded even if all ids/references are
# expired
self.assert_sql_execution(
testing.db,
session.flush,
AllOf(
# ensure all three m2os are loaded.
# the selects here are in fact unexpiring
# each row - the m2o comes from the identity map.
CompiledSQL(
"SELECT addresses.id AS addresses_id, addresses.user_id AS "
"addresses_user_id, addresses.email_address AS "
"addresses_email_address FROM addresses WHERE addresses.id = "
":param_1",
lambda ctx: {'param_1': c1id}
),
CompiledSQL(
"SELECT addresses.id AS addresses_id, addresses.user_id AS "
"addresses_user_id, addresses.email_address AS "
"addresses_email_address FROM addresses WHERE addresses.id = "
":param_1",
lambda ctx: {'param_1': c2id}
),
CompiledSQL(
"SELECT users.id AS users_id, users.name AS users_name "
"FROM users WHERE users.id = :param_1",
lambda ctx: {'param_1': pid}
),
),
CompiledSQL(
"DELETE FROM addresses WHERE addresses.id = :id",
lambda ctx: [{'id': c1id}, {'id': c2id}]
),
CompiledSQL(
"DELETE FROM users WHERE users.id = :id",
lambda ctx: {'id': pid}
),
)
def test_many_to_many(self):
mapper(Item, items, properties={
@@ -502,17 +570,52 @@ class SingleCycleTest(UOWTest):
sess = create_session()
n1 = Node(data='n1')
n1.children.append(Node(data='n11'))
n1.children.append(Node(data='n12'))
n12 = Node(data='n12')
n1.children.append(n12)
n1.children.append(Node(data='n13'))
n1.children[1].children.append(Node(data='n121'))
n1.children[1].children.append(Node(data='n122'))
n1.children[1].children.append(Node(data='n123'))
sess.add(n1)
sess.flush()
# self.assert_sql_execution(
# testing.db,
# sess.flush,
# )
self.assert_sql_execution(
testing.db,
sess.flush,
CompiledSQL(
"INSERT INTO nodes (parent_id, data) VALUES "
"(:parent_id, :data)",
lambda ctx:{'parent_id':None, 'data':'n1'}
),
CompiledSQL(
"INSERT INTO nodes (parent_id, data) VALUES "
"(:parent_id, :data)",
lambda ctx:{'parent_id':n1.id, 'data':'n11'}
),
CompiledSQL(
"INSERT INTO nodes (parent_id, data) VALUES "
"(:parent_id, :data)",
lambda ctx:{'parent_id':n1.id, 'data':'n12'}
),
CompiledSQL(
"INSERT INTO nodes (parent_id, data) VALUES "
"(:parent_id, :data)",
lambda ctx:{'parent_id':n1.id, 'data':'n13'}
),
CompiledSQL(
"INSERT INTO nodes (parent_id, data) VALUES "
"(:parent_id, :data)",
lambda ctx:{'parent_id':n12.id, 'data':'n121'}
),
CompiledSQL(
"INSERT INTO nodes (parent_id, data) VALUES "
"(:parent_id, :data)",
lambda ctx:{'parent_id':n12.id, 'data':'n122'}
),
CompiledSQL(
"INSERT INTO nodes (parent_id, data) VALUES "
"(:parent_id, :data)",
lambda ctx:{'parent_id':n12.id, 'data':'n123'}
),
)
def test_singlecycle_flush_size(self):
mapper(Node, nodes, properties={
@@ -548,6 +651,76 @@ class SingleCycleTest(UOWTest):
n1.children
self._assert_uow_size(sess, 2)
def test_delete_unloaded_m2o(self):
mapper(Node, nodes, properties={
'parent':relationship(Node, remote_side=nodes.c.id)
})
parent = Node()
c1, c2 = Node(parent=parent), Node(parent=parent)
session = Session()
session.add_all([c1, c2])
session.add(parent)
session.flush()
pid = parent.id
c1id = c1.id
c2id = c2.id
session.expire(parent)
session.expire(c1)
session.expire(c2)
session.delete(c1)
session.delete(c2)
session.delete(parent)
# testing that relationships
# are loaded even if all ids/references are
# expired
self.assert_sql_execution(
testing.db,
session.flush,
AllOf(
# ensure all three m2os are loaded.
# the selects here are in fact unexpiring
# each row - the m2o comes from the identity map.
CompiledSQL(
"SELECT nodes.id AS nodes_id, nodes.parent_id AS "
"nodes_parent_id, "
"nodes.data AS nodes_data FROM nodes "
"WHERE nodes.id = :param_1",
lambda ctx: {'param_1': pid}
),
CompiledSQL(
"SELECT nodes.id AS nodes_id, nodes.parent_id AS "
"nodes_parent_id, "
"nodes.data AS nodes_data FROM nodes "
"WHERE nodes.id = :param_1",
lambda ctx: {'param_1': c1id}
),
CompiledSQL(
"SELECT nodes.id AS nodes_id, nodes.parent_id AS "
"nodes_parent_id, "
"nodes.data AS nodes_data FROM nodes "
"WHERE nodes.id = :param_1",
lambda ctx: {'param_1': c2id}
),
),
CompiledSQL(
"DELETE FROM nodes WHERE nodes.id = :id",
lambda ctx: [{'id': c1id}, {'id': c2id}]
),
CompiledSQL(
"DELETE FROM nodes WHERE nodes.id = :id",
lambda ctx: {'id': pid}
),
)
class SingleCyclePlusAttributeTest(_base.MappedTest,
testing.AssertsExecutionResults, AssertsUOW):
@classmethod