On Oct 12, 2013, at 11:54 AM, Marc Van Olmen <[email protected]> wrote:
> hi,
>
> Just wanted to quickly report this issue, didn't had time to write unit test
> for corning the case:
> Was upgrading an 0.4.8 legacy project to 0.8.2
>
> Got an SAWarning: This collection has been invalidated in the following case:
>
> Original 0.4.8 code:
>
> self._serials.append(MetaSerial(value=u'))
>
> And failed to add it to the collection.
>
> The fix needed to get rid of the above warning:
>
> a_serial = MetaSerial(value=u'')
> self._serials.append(a_serial)
there's nothing in the mapping or sample code illustrated here that by itself
would emit this warning. The warning itself is not a bug, but instead refers
to a bug in the calling code, where it is erroneously appending to a collection
that is no longer valid, due to expiration. Expiration on session commit was
introduced as a default behavior in 0.5 and the collection mechanics also
changed significantly from 0.5 on forward.
The code example you have suggests a premature garbage collection of some
resource due to the way MetaSerial is not assigned to a variable in one case
vs. the other, but that's not really possible with a straight append to a
mapped collection as above, and that also doesn't have any direct path to
causing this very specific collection-oriented warning from being emitted. So
either this code isn't the primary cause of the issue, or there's something
more complex going on in the actual classes and/or mappings that produces this.
To produce the warning, you have to do something equivalent to the sample code
below:
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)
bs = relationship("B")
class B(Base):
__tablename__ = 'b'
id = Column(Integer, primary_key=True)
a_id = Column(Integer, ForeignKey('a.id'))
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
sess = Session(e)
a1 = A()
a1.bs = [B()]
# hold onto the collection
collection = a1.bs
sess.add(a1)
# "collection" is now no longer associated with a1
sess.commit()
# emits the warning
collection.append(B())
signature.asc
Description: Message signed with OpenPGP using GPGMail
