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
-~----------~----~----~----~------~----~------~--~---

Reply via email to