this depends on what your definition of "used" means. A save() is a
passive operation that does not interact with the database at all.
You'd have to explain to me what it is Zope needs to do with objects
at the moment of save() (and what about update? in 0.5 they are merged
into just add()), that cannot be handled at flush or query execution
time. Hooking into individual save() operations can be expensive
since a save() operation can cascade to any number of child items.
OTOH, if you need zope to wake up whenever anything on the Session at
all is called, I'd suggest a wrapper or subclass of Session. The
"sessionmaker()" concept makes this very easy since you get to plug in
whatever session factory you want using the "class_" parameter.
> On the moment of save, I need to join the SQLAlchemy transaction to
> the Zope transaction, so that Zope knows to commit the SQLAlchemy
> transaction when it's transaction is committed. At the moment this
> join is happening only on first database access, but it's possible to
> add an instance without triggering any database access, with the
> result that the sqlalchemy session is not committed when zope does
> it's transaction.commit().
Oh, OK, the Zope transaction is already in progress. The Session gets
used, possibly just save() and nothing else, then the Zope transaction
is committed.
> I would rather only hook in once, but adding the hook into every
> attach seems the easiest way to do it. The 'have I hooked in already'
> logic moves to the SessionExtension, but I don't think this is a
> problem. In zope.sqlalchemy this overhead is only the method call and
> one dictionary lookup.
OK, the patch is pretty harmless for 0.5, but it does make an
imposition as to how objects are "attached" to the Session now. In
particular, objects which are loaded from a database result set are
not attached through this route, which means we have to always ensure
that _attach() doesn't get called by any other avenue than those
defined (i.e. add(), delete(), merge(), and equivalents). We just
had someone else building an on-save() validator so two use case
requests in a week generally imply we should do something about it so
its in r4932, however the method receives the instance and not the
state, since the state is generally an SA-internal construct.
>
> I'd like to avoid this if I possibly can so that people are just using
> SQLAlchemy rather than a magic zope layer in between.
>
Though I am curious why a Session isn't part of the Zope transaction
from it's inception ? Why not just link the creation of the Session
itself to the transaction association process ? The user needs to
build the sessionmaker() in a Zope-aware way regardless.
>