might say SELECT A.*, B.* FROM A JOIN X, B JOIN Y.
Eager loading can also tack its joins onto those
multiple FROM clauses. [ticket:1337]
+
+ - Fixed bug in dynamic_loader() where append/remove events
+ after construction time were not being propagated to the
+ UOW to pick up on flush(). [ticket:1347]
- Fixed bug where column_prefix wasn't being checked before
not mapping an attribute that already had class-level
)
from sqlalchemy.orm.query import Query
from sqlalchemy.orm.util import _state_has_identity, has_identity
-
+from sqlalchemy.orm import attributes
class DynaLoader(strategies.AbstractRelationLoader):
def init_class_attribute(self, mapper):
collection_history = self._modified_event(state)
collection_history.added_items.append(value)
- if self.trackparent and value is not None:
- self.sethasparent(attributes.instance_state(value), True)
for ext in self.extensions:
ext.append(state, value, initiator or self)
+ if self.trackparent and value is not None:
+ self.sethasparent(attributes.instance_state(value), True)
+
def fire_remove_event(self, state, value, initiator):
collection_history = self._modified_event(state)
collection_history.deleted_items.append(value)
ext.remove(state, value, initiator or self)
def _modified_event(self, state):
- state.modified = True
+
if self.key not in state.committed_state:
state.committed_state[self.key] = CollectionHistory(self, state)
+ state.modified_event(self, False, attributes.NEVER_SET, passive=attributes.PASSIVE_NO_INITIALIZE)
+
# this is a hack to allow the _base.ComparableEntity fixture
# to work
state.dict[self.key] = True
not self._deleted and not self._new):
return
+
dirty = self._dirty_states
if not dirty and not self._deleted and not self._new:
self.identity_map.modified = False
import operator
from sqlalchemy.orm import dynamic_loader, backref
from testlib import testing
-from testlib.sa import Table, Column, Integer, String, ForeignKey, desc
+from testlib.sa import Table, Column, Integer, String, ForeignKey, desc, select, func
from testlib.sa.orm import mapper, relation, create_session, Query
from testlib.testing import eq_
from testlib.compat import _function_named
class FlushTest(_fixtures.FixtureTest):
run_inserts = None
+ @testing.resolve_artifact_names
+ def test_events(self):
+ mapper(User, users, properties={
+ 'addresses':dynamic_loader(mapper(Address, addresses))
+ })
+ sess = create_session()
+ u1 = User(name='jack')
+ a1 = Address(email_address='foo')
+ sess.add_all([u1, a1])
+ sess.flush()
+
+ assert testing.db.scalar(select([func.count(1)]).where(addresses.c.user_id!=None)) == 0
+ u1 = sess.query(User).get(u1.id)
+ u1.addresses.append(a1)
+ sess.flush()
+
+ assert testing.db.execute(select([addresses]).where(addresses.c.user_id!=None)).fetchall() == [
+ (1, u1.id, 'foo')
+ ]
+
+ u1.addresses.remove(a1)
+ sess.flush()
+ assert testing.db.scalar(select([func.count(1)]).where(addresses.c.user_id!=None)) == 0
+
+
+
+
@testing.resolve_artifact_names
def test_basic(self):
mapper(User, users, properties={