ColumnPoperty.merge() w/ load=False calls expire_attributes on a deferred, forcing it to load on unexpire
Issue #3488
resolved
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
d1 = deferred(Column(String))
d2 = Column(String)
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
a1 = A(d1='d1', d2='d2')
s = Session(e)
s.add(a1)
s.commit()
s.close()
a1 = s.query(A).first()
s.expire(a1, ['d2'])
s.close()
a1 = s.merge(a1, load=False)
print "---------------"
# emits load for d1 also
print a1.d2
this is not the fix because it does not take the strategy itself or load_options into account, but this is the idea:
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index 55e0298..2bc9626 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -217,7 +217,7 @@ class ColumnProperty(StrategizedProperty):
else:
impl = dest_state.get_impl(self.key)
impl.set(dest_state, dest_dict, value, None)
- elif dest_state.has_identity and self.key not in dest_dict:
+ elif dest_state.has_identity and self.key not in dest_dict and not self.deferred:
dest_state._expire_attributes(dest_dict, [self.key])
class Comparator(util.MemoizedSlots, PropComparator):
Comments (5)
-
reporter -
reporter -
assigned issue to
- edited description
-
assigned issue to
-
A pull request with the above patch, plus some tests:
-
reporter - changed status to resolved
- don't load deferred columns on unexpire for merge with load=False,
fixes
#3488
Change-Id: Ic9577b800e4a4e2465ec7f3a2e95bd231f5337ee Co-Authored-By: Mike Bayer mike_mp@zzzcomputing.com
→ <<cset bef15a950ec4>>
-
reporter Merge "- don't load deferred columns on unexpire for merge with load=False, fixes
#3488"→ <<cset 829bd30834cc>>
- Log in to comment
here's the final patch w/o tests, which also introduces that we copy the callables_ over from the loaded state:
tests are:
and then for the local callable: