Hello Joel,

web2py has change since one year ago. Now you simply do:

   db.define_table('mytable',....fields...,auth.signature)
   ... define more table ...
   auth.enable_record_versioning(db)

and mytable will have a mytable_archive that works as Nick suggested.

On Tuesday, 3 July 2012 16:15:26 UTC-5, Joel Carrier wrote:
>
> Hi Nick Name,
>
> Did you ever find a solution that met all your requirements?  What you've 
> described is exactly what I am facing now.
>
> Joel
>
> On Friday, May 6, 2011 6:18:49 PM UTC-4, nick name wrote:
>>
>> My use of web2py requires an audit trail for (essentially) all database 
>> tables; The preferable way to do that is to keep a "foo_history" table for 
>> each table "foo". The records (both audited and original) need to have a 
>> "revision" that increments with each update, and "last modified on", "last 
>> modified by" fields that get updated with the user_id and the time on each 
>> update.
>>
>> At this point in time, there is no need to delete records - but if there 
>> was, I'm not sure what the proper way would be -- possibly having another 
>> field "deleted" on the audit trail table, which would be set to "true" on 
>> the revision that was the latest version.
>>
>> Now, the built in Crud system gives me most of what I want (I don't see 
>> how to make it keep the history of the deleted table above, though for now 
>> that's not a problem). But there's quite a bit of application logic that 
>> needs this which cannot be implemented using the Crud.
>>
>> The "classic" solution is to write this as stored procedures. I would 
>> like to avoid that for portability and maintenance reasons. Another 
>> solution is to use my own "update/insert/delete" methods that update audit 
>> tables whenever a record updates. That's error prone, and I would rather 
>> avoid that, especially since I _do_ want to build on web2py infrastructure 
>> such as Crud for other things.
>>
>> The solution that I'm thinking of is to hook the DAL; specifically, the 
>> following functions would be sufficient for me; It seems that all database 
>> modifications go through them eventually, whether called directly or when 
>> manipulating Rows or Row objects.
>>
>> insert: (copy all newly added records to the audit table table - easy)
>> update: (copy all modified records to the audit table, add a 'revision = 
>> revision + 1' to the SET code - easy)
>> delete: (copy all deleted records to the audit table, adding a 'deleted = 
>> True' - possibly a little more complicated)
>>
>> For completeness, hooking "truncate" and "drop table" to do the same 
>> thing (either raise an error if that is disallowed, or transform it into a 
>> delete of each individual record so that everything goes into the audit). 
>> And I would also disable migrations if I do that, because they may change 
>> the database without updating my audit trail.
>>
>> Now, before I start working on a monkey patch (or full patch) to dal.py - 
>> perhaps I've missed a simpler way to do the same thing?
>>
>> If I haven't - I'm currently working with Postgres and SQLite; I would 
>> like to contribute the resulting patch to the web2py project, but have no 
>> time to evaluate and test on other databases/gae at the moment. Is there 
>> anything else I should be aware of that would be required for other 
>> databases?
>>  
>> ====
>>
>> Finally, a question about transaction rollback - in my app, I sometimes 
>> want to rollback everything (as if I did e.g. raise 
>> MySecurityException("Forbidden")), but actually return a non-error HTML 
>> result to the user. I am aware of db.rollback(), but the exception handling 
>> code does more, e.g., today it does:
>>
>>  if response._custom_rollback:
>>    response._custom_rollback()
>>  else:
>>    BaseAdapter.close_all_instances('rollback')
>>
>> I would suggest adding an "response._transaction_verb" variable, which 
>> would default to 'COMMIT', but could be changed to 'ROLLBACK', and would 
>> determine what to do with the database (commit/rollback) in the case of a 
>> successful completion - meaning raising of an HTTP exception or simple 
>> return from controller.
>>
>> On other exception, I would expect rollback always (and the application 
>> code can call db.commit or BaseAdapter.close_all_instances('commit') or 
>> whatever if needed) - because committing on error is something that has to 
>> be extremely explicit.
>>
>> What say you?
>>
>

Reply via email to