On Dec 10, 2007, at 3:07 PM, Adam Batkin wrote:
> Can you suggest other alternatives for the above use case? Having to
> call flush before doing anything that might require the ID seems
> excessive and too low-level for code like that.
>
> I know for a fact that Hibernate does it this way (not that sqlalchemy
> has to do everything Hibernate does), and I can't imagine a use case
> where doing what's needed to retrieve database-generated fields on an
> as-needed basis would be considered incorrect behavior.
>
ive never seen that one before, i.e. the id generator being called in
direct reaction to calling myentity.getId(). In our hibernate apps we
often check for the id being null in order to check if the entity is
persisted yet. if you only mean that hibernate generates its own IDs
externally to INSERTs, yes thats true. SQLAlchemy would not use that
method by default since most of our users want to use their databases
native ID generation utilities, which on sqlite, mysql and others
only occur during INSERT, but we have no issue with providing that
method of id generation as an option if people want it (and of course
we have the hooks for user-defined default generation functions).
So, im assuming the desired feature here (before getting into your
furher comments below) is, upon access to a primary key attribute, get
the id, *without* issuing an INSERT or a flush, and assign it to the
attribute. Thats pretty easy to do provided you dont mind using a non-
native id generation method on certain databases.
So, first to get the id, either:
1. use a sequence, dont use mysql or sqlite
2. use an external id generation function. if youd like to provide
ones that work with databases like mysql and sqlite, and they are
atomic/threadsafe/all that good stuff, we can add them as features.
i dont get into those myself because of the various issues with
atomcity but ive no issue with using one that is properly constructed.
So if either ID generation function of #1 or #2 is available, they can
easily be installed on a mapped class. Theres three ways this can be
done, and the first two you can play with without us modifying
SQLAlchemy at all.
1. just build a class property which checks for none, calls the id
generator and applies. 0.4.2 has an easier syntax for setting up
"synonyms" which allow you to decorate the behavior of a class
attribute, but you can do this with any version of SA (just that it
works better in 0.4.2).
2. I can show you the less-than-public API we use to put "value
generation" callables on attributes, i.e. the same one that issues
deferred loads and lazy relation loads. this would be a little more
like the start of an actual feature.
3. building on #2 would be some feature to SA called "eager-fetch-ids"
or something like that, which looks at the Column for a
DefaultGenerator that is executable (Sequences, for example, are
executable DefaultGenerator objects). it would probably just take a
list of keys and apply to any columns you want, not just pk cols.
I dont consider the above behavior, or lack of it, to be "correct" or
"incorrect". i think most of our users would be surprised by it and
would prefer to leave it off, but if some people prefer it thats fine
by me.
now the next comment, much deeper can of worms:
> "As far as the application is concerned, objects in the Pending and
> Persistent states should function identically."
OK, above we are talking just about primary key generation...its not
that big a deal. But here, the difference between pending and
persistent is huge. If your proposal is, "pending acts just like
persistent, without flushing", i would ask how you'd approach these
examples:
x = Foo()
print x.id # generates id, prints 1
enhedgine.execute("select * from table where id=" + x.id)
above, the query is directly to the DB.
Another example, which we actually support right now...but its because
a flush occurs:
x = Foo()
x.id = 7
for a in x.addresses: # lazy load of "where x=7".
> (it's possible that this feature would be difficult to implement, in
> which case that's a good answer and maybe it can go on to a far-off
> wishlist, or I can try to implement it or something, I just don't
> see a
> way for it to be considered incorrect behavior)
like i said none of this is "incorrect", but if you are getting at the
idea that we'd start querying for things within the session that
havent been flushed, i.e. effectively building our own "select" engine
in python, that would get really hairy. we will eventually implement
some invalidation of persistent objects based on criterion, but thats
about it, and that can still issue SQL if it needs to since it only
acts on persistent instances.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected]
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
-~----------~----~----~----~------~----~------~--~---