On 01/17/2011 05:14 PM, Michael Bayer wrote:
On Jan 16, 2011, at 8:15 PM, Jan Mueller wrote:

Ok then i will try to explain it:

I have a pylons web application... and i want to use the entity attribute 
updated_at as a Datetime version_id...
so i modified the entity with the mapper args and put a hidden input field in 
my edit html forms for the updated_at value... in order to preserve it... i got 
this idea from some newsgroup some days ago... i don't remember exactly where...
this approach is quite simpler, than saving the state respectively the entity 
object to an http session... or any other smaller server-side context... like 
in jee
another point is... i think this wouldn't be possible with pylons... because of 
the serialization of objects saved to the http session object... i remember to 
have read something like this about pylons...

so if the user commits the form i take all input values and set them at an 
entity object. This entity object is not attached to the unit of work (i think 
it is called like this in sqlalchemy?) but it will get attached at the moment, 
when i call session.merge(item) (at least this is what the documentation 
says)... i only want to clarify this?!

so the behavior i need is, that the manually set version_id is used to identify 
the record in the database table... during the update... and with version>= 
0.6.4 this does not work... maybe it works with an extremely complex 
configuration... but i don't know which one this should be...
That is how it works, except the value that matches in the UPDATE has to be the 
database-loaded value of updated_at.    Part of the state you have present is 
what was loaded from the database, part of it is what you've changed.  That 
also changed in 0.6.4.
Yes that makes sense... if the version_id attribute was loaded from the database and is on update not the same as the one in the database... you know someone else modified it and you can throw the staledataerror... i would think of it as the right way... and i also guess this is the behavior of hibernate. If you can preserve the object and the Session (unit of work) it is attached to within the memory of the server, the version_id will behave like it should, but does the object has to be attached to the unit of work all the time in order for sqla to know if the present value was the one "loaded from the database"? if not... i would simply store the loaded object into the beaker session, which is stored with pickle to a file at the end of every http request... load it back from the beacker session at the next request... modify it (not the updated_at but everything else)... and merge it ... and commit it... and version_id_col behavior should do the trick?!

by preserving the state information of the version_id through the webbrowser it would be possible to modify the hidden input field to the current value in the database in order to get the record stored, in order to circumvent the staledataerror... which wouldn't be possible if the state was preserved on the server-side...

but the hidden input field makes it easy to use and reduces the load on the server, which could increase drastically if there were many concurrent edit events...
So here you want to receive the version id from your hidden field, and detect 
if that version is obsolete.

A better way to do this, since it's explicit, is to just say:

        try:
                obj = Session.query(MyObject).filter(MyObject.updated_at == 
my_hidden_updated_at).filter(MyObject.id == id).one()
         except orm.exc.NoResultFound:
                 print "stale version !"

         form.populate_object(obj)
yes but then you don't have the assurance of exclusion... i mean it would be possible, that someone else saved it between your query above and the update operation which should follow this query... checking and saving has to be atomic... like it is... with the update ... where id="id" and updated_at="edited_version_updated_at"...
However, interesting here is that you're merging, and I wonder if merge() 
should be also checking version_id col for a stale version - that might be the 
correct way for SQLA to behave in this case.  I'm going to check what Hibernate 
does since both of these features came from Hibernate.

furthermore it is necessary that the manually set version_id is newly generated 
by version_id_generator for the update statement... because the intention of 
version_id during update is not to be set manually... but to be generated over 
and over again... i cannot think of a scenario where this shouldn't be the 
intended behavior?! because the version_id is a completely managed attribute... 
it doesn't make any sense to really set it manually and flush this to the db...
Some people want to bump the version_id manually.   I think its a surprise behavior if 
someone says myobject.version_id= x, flushes it, then 'x' silently disappears.    If 
version_id is to be entirely "managed" and not to be set outside of the flush, 
then setting a value should raise an error at least.     In this case if you no longer 
rely upon setting updated_at as a means to locate the current object, since merge() is 
likely not honoring updated_at like it should be (or we change merge() to check the 
updated_at), then this is no longer an issue.,
i thought it's the only intention of a version_id... to be used for versioning, satisfy the needs of "optimistic locking"... and therefore to be entirely managed by the orm...

i only came up with the idea to set the version_id manually because i read it somewhere and thought it would be easier to preserve the state through the browser... you need much less code for this ... because you don't have to check, which version a user is editing at a time... in respect to the possibility he requests the edit-form more than once at a time... and has forms with older content than the one in the object or the database... so preserving the updated_at through an hidden input field would always be best... in order to know which version he was editing... although the need to set it manual wouldn't be there...

i just had to think about mediawiki which also of course checks the version of an edited part at the time of an update query... hm... i will check how they preserve the version during editing phase... ok... this is might not be interesting for you... but for me it is :)

i haven't had such an interesting conversation for a long time... thanks michael


maybe you can clarify in which way the version_id_col should behave? and which 
session configuration has to be used?

i use thread-local sqlalchemy sessions and remove those at the end of every 
request... just like the pylons doc recommends:

Session = scoped_session(sessionmaker(autocommit=False, expire_on_commit=False))

i don't know if expire_on_commit has necessarily to be False... i tested it 
with True and False... during 0.6.4 and 0.6.6 and nothing changed.
autocommit is False with default behavior... but i thought... just in case ;-)

so ... these are my thoughts about version_id_col ...

it works really fine now... with 0.6.3 ;-)

and thanks for the great orm :)

Greetings
Jan


On 01/17/2011 01:17 AM, Michael Bayer wrote:
if there's a bug in version_id_col I'd really like to know.   I don't 
understand the use case for setting the column explicitly, then having it not 
persist.


On Jan 16, 2011, at 7:11 PM, Jan Mueller wrote:

I switched to 0.6.3 and version_id_col works... just like i expected... that's 
really odd...
i guess i will stay at this version and everything will be fine ;-)

thank you very much.

and sorry for the lacky explanation of my problem.

Greetings
Jan

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


--

Greetings
Jan Müller

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