On Jan 15, 11:56 am, Tvrtko <qvx3...@gmail.com> wrote:
> First, let me say that I'm using sqlalchemy version 0.5.8. We have a
> large and complex application and changing to sa 0.6 is expensive, so
> I would like, if possible, to find a solution for 0.5. I'm using
> sqlalchemy since version 0.1.
>
> Problem: objects are one moment inside a session an the other moment
> are not.
>
> Setup:
>
> Session is in weak_identity_map=False mode:
>
>    maker = sessionmaker(autoflush=True, autocommit=False,
>         weak_identity_map=False,
>         extension=[ZopeTransactionExtension(), EpiSessionExtension()])
>     DBSession = scoped_session(maker)
>
> All objects are immediately added to session:
>
>     campaign = Campaign(...)
>     DBSession.add(campaign)
>
> Plus, the reference to object is kept locally.
> Plus, the object is assigned to another relation property:
>
>     qitem = QItem(campaign=campaign, ...)
>     DBSession.add(qitem)
>
> Now, the problem occurs at two different random points. Both time
> the garbage collector is collecting the garbage before the problem
> presents itself. This may have nothing to do with a problem.
>
> Everything happens inside a single thread.
>
> First case:
>
>     campaign = Campaign(...)
>     DBSession.add(campaign)
>     ...
>     # called indirectly because of lots of queries
>     DBSession.flush()
>     print campaign.id  # 206
>
>     # A: the (<Campaign>, 206) is inside the keys
>     print DBSession.identity_map.keys()
>
>     contact = DBSession.query(...).one()
>     # garbage is collected while this runs
>     # I can see it because of gc.set_debug(...)
>     # However, campaign is referenced locally and gc
>     # leaves it, but maybe some other internal SA object
>     # is collected.
>
>     # B: the (<Campaign>, 206) is no longer present
>     print DBSession.identity_map.keys()

Actually, this case is the same as the second case, so let's just
ignore it.
The objects are not expunged from the session without a reason as the
example might suggest. Objects are removed because the automatic
`flush()`
inside `query()` failed and rolled back the transaction (and removed
objects from session). "B" print was done inside exception handler.

So, it really is the same case as the second one:

> Second case, very similar, but problem appears at a later point:
>
>     campaign = Campaign(...)
>     DBSession.add(campaign)
>     DBSession.flush()
>     print campaign.id  # 207
>     contact = DBSession.query(...).one()
>
>     # Also, assign campaign to relational property of `qitem`
>     qitem = QItem(campaign=campaign, ...)
>     DBSession.add(qitem)
>
>     # The (<Campaign>, 207) is inside the keys
>     print DBSession.identity_map.keys()
>
>     DBSession.flush() # called via commit by web controller
>     # DB raises exception CONTACT_ID cannot be NULL

Somehow, the `qitem.campaign` relation property behaves as if it
is not set at all, and SA doesn't prepare `QITEM.CAMPAIGN_ID`
properly.

>
> The exception is raised because the `campaign` object
> again got expunged from session for some reason, even
> though the `qitem` itself holds a reference to it.

Well, maybe it wasn't expunged at that point, I dont have a proof,
but the `CAMPAIGN_ID` was set to NULL as if the `campaign`
property was not set.

-- 
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 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to