mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-06-05 15:23:48 -04:00
- session.expire() and related methods will not expire() unloaded
deferred attributes. This prevents them from being needlessly loaded when the instance is refreshed.
This commit is contained in:
@@ -35,6 +35,10 @@ CHANGES
|
||||
loading would prevent other eager loads, self referential or not,
|
||||
from joining to the parent JOIN properly. Thanks to Alex K
|
||||
for creating a great test case.
|
||||
|
||||
- session.expire() and related methods will not expire() unloaded
|
||||
deferred attributes. This prevents them from being needlessly
|
||||
loaded when the instance is refreshed.
|
||||
|
||||
- sql
|
||||
- Further fixes to the "percent signs and spaces in column/table
|
||||
|
||||
@@ -775,7 +775,12 @@ class Mapper(object):
|
||||
if prop is None and raiseerr:
|
||||
raise sa_exc.InvalidRequestError("Mapper '%s' has no property '%s'" % (str(self), key))
|
||||
return prop
|
||||
|
||||
|
||||
@util.memoized_property
|
||||
def _deferred_props(self):
|
||||
return [p.key for p in self._props.values() if
|
||||
isinstance(p, ColumnProperty) and getattr(p, 'deferred', False)]
|
||||
|
||||
@property
|
||||
def iterate_properties(self):
|
||||
"""return an iterator of all MapperProperty objects."""
|
||||
|
||||
@@ -1518,7 +1518,15 @@ class Session(object):
|
||||
|
||||
return util.IdentitySet(self._new.values())
|
||||
|
||||
_expire_state = attributes.InstanceState.expire_attributes
|
||||
def _expire_state(state, attribute_names):
|
||||
if attribute_names is None:
|
||||
state.expired = True
|
||||
state.modified= False
|
||||
# dont add unloaded deferred attributes to the list of attrs
|
||||
attribute_names = set(state.manager.keys()).\
|
||||
difference([k for k in state.manager.mapper._deferred_props if k not in state.dict])
|
||||
state.expire_attributes(attribute_names)
|
||||
|
||||
UOWEventHandler = unitofwork.UOWEventHandler
|
||||
|
||||
_sessions = weakref.WeakValueDictionary()
|
||||
|
||||
+16
-2
@@ -4,7 +4,7 @@ import testenv; testenv.configure_for_tests()
|
||||
import gc
|
||||
from testlib import sa, testing
|
||||
from testlib.sa import Table, Column, Integer, String, ForeignKey, exc as sa_exc
|
||||
from testlib.sa.orm import mapper, relation, create_session, attributes
|
||||
from testlib.sa.orm import mapper, relation, create_session, attributes, deferred
|
||||
from orm import _base, _fixtures
|
||||
|
||||
|
||||
@@ -98,7 +98,21 @@ class ExpireTest(_fixtures.FixtureTest):
|
||||
# but now its back, rollback has occured, the _remove_newly_deleted
|
||||
# is reverted
|
||||
self.assertEquals(u.name, 'chuck')
|
||||
|
||||
|
||||
@testing.resolve_artifact_names
|
||||
def test_deferred(self):
|
||||
"""test that unloaded, deferred attributes aren't included in the expiry list."""
|
||||
|
||||
mapper(Order, orders, properties={'description':deferred(orders.c.description)})
|
||||
|
||||
s = create_session()
|
||||
o1 = s.query(Order).first()
|
||||
assert 'description' not in o1.__dict__
|
||||
s.expire(o1)
|
||||
assert o1.isopen is not None
|
||||
assert 'description' not in o1.__dict__
|
||||
assert o1.description
|
||||
|
||||
@testing.resolve_artifact_names
|
||||
def test_lazyload_autoflushes(self):
|
||||
mapper(User, users, properties={
|
||||
|
||||
Reference in New Issue
Block a user