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