OK this issue is actually limited to "transient" objects only; that is, if you had flushed your session before doing the merge() it would have worked. The fix is in r4104. Im considering putting out 0.4.3 today as a mostly bugfix release but have not decided yet.
On Jan 30, 2008, at 6:14 AM, Paul-Michael Agapow wrote: > > I'm using merge to push objects into a db. (Long story short: I have > a set of objects that have to behave identically if they are > persisted or not, and may be retrieved or sent to a set of > databases. Hence the use of merge.) However, merged objects appear > object joined by a relation and backrefs twice. Is this a bug or an > I making some subtle mistake? > > A condensed demonstration - the names of the mapped objects and > tables are unimportant, but a Biosequence has a one-to-many with a > set of Annotations, established by a backref:: > > from sqlalchemy import * > from sqlalchemy.orm import * > > metadata = MetaData() > > class Biosequence (object): > pass > > class Annotation (object): > pass > > table_biosequences = Table ('biosequences', metadata, > Column ('identifier', Integer(), primary_key=True), > Column ('dummy', String(16)), > ) > > table_seqannotations = Table ('seqannotations', metadata, > Column ('identifier', Integer(), primary_key=True), > Column ('biosequence_id', Integer(), ForeignKey > ('biosequences.identifier')), > ) > > mapper (Annotation, table_seqannotations) > mapper (Biosequence, table_biosequences, > properties={ > 'annotations':relation ( > Annotation, > backref='biosequence_ref', > lazy=False, > cascade="all, delete, delete-orphan", > ), > }, > ) > > engine = create_engine ('sqlite:///', convert_unicode=True, > # echo=True, > ) > sessionfactory = sessionmaker (bind=engine, autoflush=False, > transactional=False) > session = sessionfactory() > metadata.create_all (bind=engine, checkfirst=True) > > # make an object with 3 'children' > bseq = Biosequence() > anns = [Annotation() for x in range (3)] > bseq.annotations = anns > print "Original num of anns:", len (bseq.annotations) > > # the merged copy has 6 children > merge_bseq = session.merge (bseq) > session.flush() > print "Now num of anns still:", len (bseq.annotations) > print "Ids:", [x.identifier for x in bseq.annotations] > print "Merged copy num of anns:", len (merge_bseq.annotations) > print "Ids:", [x.identifier for x in merge_bseq.annotations] > > # as does the return! > results = session.query (Biosequence) > print "Number of results", results.count() > returned_bseq = results.one() > print "Returned num of anns:", len (returned_bseq.annotations) > print "Ids:", [x.identifier for x in returned_bseq.annotations] > > # make an new object with 3 children > bseq2 = Biosequence() > bseq2.annotations = [Annotation() for x in range (3)] > print "New obj num of anns:", len (bseq.annotations) > session.save_or_update (bseq2) > session.flush() > > # and it works as expected > results = session.query (Biosequence) > print "Number of retreived objects", results.count() > returned_bseqs = results.all() > for item in returned_bseqs: > print "Returned num of anns:", len (item.annotations) > print "Ids:", [x.identifier for x in item.annotations] > > > Which returns:: > > Original num of anns: 3 > Now num of anns still: 3 > Ids: [None, None, None] > Merged copy num of anns: 6 > Ids: [1, 1, 2, 2, 3, 3] > Number of results 1 > Returned num of anns: 6 > Ids: [1, 1, 2, 2, 3, 3] > New obj num of anns: 3 > Number of retreived objects 2 > Returned num of anns: 6 > Ids: [1, 1, 2, 2, 3, 3] > Returned num of anns: 3 > Ids: [4, 5, 6] > > In summary: if an object is stored using 'save_or_update', when > later retrieved, it has the correct number of related children. If > merged, the returned merge copy has each child twice. If this object > is retrieved later, it still has every child twice. Looking at the > db, the correct number of child rows is being stored and the > relations are correct. It therefore looks like there's a problem in > the session for merged objects. > > Any pointers? > > -- > Dr Paul-Michael Agapow: VieDigitale / Inst. for Animal Health > [EMAIL PROTECTED] / [EMAIL PROTECTED] > > > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---