session.merge(p) will add a new object as “pending” if it does not exist in the database yet. if it does exist, then it will be “persistent”. within merge(), the session will emit an autoflush before it begins, so anything that is pending at that point will become persistent. Within the merge itself, autoflush is set to false so that any queries within the process won’t trigger another autoflush.
Follow the demonstration below which illustrates this. Also the talk I gave at http://techspot.zzzeek.org/2012/11/14/pycon-canada-the-sqlalchemy-session-in-depth/ goes over this in detail. 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) data = Column(String) engine = create_engine("sqlite://", echo=True) Base.metadata.create_all(engine) s = Session(engine) a1 = A(id=1, data='a1') s.add(a1) s.commit() s.close() s = Session(engine) a1_persistent = A(id=1) a2_pending = A(id=2) # merge persistent. autoflush, then it loads id=1 and # populates. a1_persistent_merged = s.merge(a1_persistent) # it's marked as "dirty" because attributes were touched... assert a1_persistent_merged in s.dirty # but it actually has no net changes, so won't actually be flushed assert not s.is_modified(a1_persistent_merged) # but it is persistent. assert inspect(a1_persistent_merged).persistent # merge pending. autoflush, then it attempts to load id=2, # doesn't find it, adds object to session.new a2_pending_merged = s.merge(a2_pending) # inspect reveals a2 is pending assert inspect(a2_pending_merged).pending # and is in .new assert a2_pending_merged in s.new # now it's not s.flush() assert a2_pending_merged not in s.new On Feb 28, 2014, at 7:19 AM, Bao Niu <niuba...@gmail.com> wrote: > As a follow-up question to my last post, could someone please explain a bit > why using session.add() would add a new item in session.new while using > session.merge() would add a new item in session.dirty? Even when the merge() > actually creates a new instance by querying the database? > I thought merge() should cause the same effect as add() when it creates a new > instance in IdentitySet(). Why is there such a difference? > > > On Wednesday, February 26, 2014 10:16:26 PM UTC-8, Bao Niu wrote: > From my study of the documentation, it seems to be the case that the state of > "pending" refers to the set of instances that is the sum of both session.new > and session.dirty. Is this understanding correct? > > In addition, using session.add() will almost always lead to a new item in > session.new, while using session.merge() will almost always lead to a new > item in session.dirty. For example, if I have an instance named p. > > If I use session.add(p): > >>>session.add(p) > >>>session.new > IdentitySet(([<__main__.P object at 0xb69fbc0c>]) > >>>session.dirty > IdentitySet([]) > > If I use session.merge(p): > >>>session.merge(p) > >>>session.new > IdentitySet([]) > >>>session.dirty > IdentitySet(([<__main__.P object at 0xb69fbc0c>]) > > > So, the conclusion is: > session.add ==> a new item added to session.new > session.merge ==> a new item added to session.dirty > session.add + session.merge ==> "pending" > > Is my conclusion correct? > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at http://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/groups/opt_out.
signature.asc
Description: Message signed with OpenPGP using GPGMail