Re: How do you rollback a transaction outside the context of a request?

2010-04-15 Thread Bill Freeman
The difficulty with the decorator approach is that, at least in the case of my
"DataError", in the course of executing modelinstance.save(), nobody has
called transaction.set_dirty(), so the commit_on_success decorator's
wrapper doesn't call rollback.

If I caught the error inside of the wrapper, I could call rollback myself.
But the wrapper has this nice handler that I'd like to use.

So, if I call transaction.set_dirty() before the first save in my wrapped
function, everything appears to work.  For previous times through the
loop, where there were no errors, commit_on_success's wrapper will
have called commit.  I'm assuming that the rollback will only roll back to
the most recent commit, so I won't be loosing things from previous
successful iterations of the loop that calls the wrapped function.  So I
don't need to become involved in savepoints.

Does anyone spot a fallacy?

Bill

On Thu, Apr 15, 2010 at 11:27 AM, Bill Freeman  wrote:
> I'm following you now.  I was reading through the transaction.py code after
> David's post, and had just come to the same conclusion.
>
> I have a function (called in a loop) that contains all my model get's and 
> saves,
> so I tried the commit_on_success decorator.  Sadly, the next database
> interaction after the failing save, which is a get in the beginning of the
> function on the next time through the loop, fails with:
>
>   current transaction is aborted, commands ignored until end of
> transaction block
>
> Perchance I also need to create a savepoint and do savepoint_rollback?
>
> Bill
>
> On Thu, Apr 15, 2010 at 11:03 AM, Thomas Guettler  wrote:
>>
>>
>> Bill Freeman wrote:
>>> How does this apply when there is no request?  I'm not following you.
>>
>> I forgot to say, that I would create a temporary script file which
>> uses the decorator commit_on_success instead of using "manage.py shell".
>>
>>  Thomas
>>
>>
>> --
>> Thomas Guettler, http://www.thomas-guettler.de/
>> E-Mail: guettli (*) thomas-guettler + de
>>
>> --
>> You received this message because you are subscribed to the Google Groups 
>> "Django users" 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/django-users?hl=en.
>>
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" 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/django-users?hl=en.



Re: How do you rollback a transaction outside the context of a request?

2010-04-15 Thread Bill Freeman
I'm following you now.  I was reading through the transaction.py code after
David's post, and had just come to the same conclusion.

I have a function (called in a loop) that contains all my model get's and saves,
so I tried the commit_on_success decorator.  Sadly, the next database
interaction after the failing save, which is a get in the beginning of the
function on the next time through the loop, fails with:

   current transaction is aborted, commands ignored until end of
transaction block

Perchance I also need to create a savepoint and do savepoint_rollback?

Bill

On Thu, Apr 15, 2010 at 11:03 AM, Thomas Guettler  wrote:
>
>
> Bill Freeman wrote:
>> How does this apply when there is no request?  I'm not following you.
>
> I forgot to say, that I would create a temporary script file which
> uses the decorator commit_on_success instead of using "manage.py shell".
>
>  Thomas
>
>
> --
> Thomas Guettler, http://www.thomas-guettler.de/
> E-Mail: guettli (*) thomas-guettler + de
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Django users" 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/django-users?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" 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/django-users?hl=en.



Re: How do you rollback a transaction outside the context of a request?

2010-04-15 Thread Thomas Guettler


Bill Freeman wrote:
> How does this apply when there is no request?  I'm not following you.

I forgot to say, that I would create a temporary script file which
uses the decorator commit_on_success instead of using "manage.py shell".

  Thomas


-- 
Thomas Guettler, http://www.thomas-guettler.de/
E-Mail: guettli (*) thomas-guettler + de

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" 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/django-users?hl=en.



Re: How do you rollback a transaction outside the context of a request?

2010-04-15 Thread Thomas Guettler


Bill Freeman wrote:
> How does this apply when there is no request?  I'm not following you.
> 

I wrote:

>> Only methods that are called from the shell (scripts in bin/...) have the 
>> commit_on_success decorator.

With shell I mean a unix like shell, cron-job or something like this, where you 
have no request.
I explained it in my first post.

  Thomas

-- 
Thomas Guettler, http://www.thomas-guettler.de/
E-Mail: guettli (*) thomas-guettler + de

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" 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/django-users?hl=en.



Re: How do you rollback a transaction outside the context of a request?

2010-04-15 Thread David De La Harpe Golden

On 14/04/10 23:15, Bill Freeman wrote:



The trouble is, I don't know how.  Just calling django.db.transaction.rollback()
doesn't work, and neither do several other guesses.



N.B. Despite eventually signalling a TransactionManagementError if 
django doesn't "think" it's in a transaction-managed chunk, that method 
typically _does_ successfully roll back the current db transaction 
(ultimately with the connection._rollback() private method already 
mentioned by Joe) prior to signalling the error.  Which is a bit 
confusing, yes.


Perhaps it would be nice if the interactive shell had an option to start 
up already in the transaction managed mode*, but in the meantime you can 
manage it  yourself -


"just" interactively pretend to be some of the transaction management 
setup code at the shell prompt, and you can avoid that error being 
raised upon rollback()  - i.e. before and after your stuff, type in what 
@commit_manually does before and after the functions it decorates to 
switch into and out of managed mode:


See source, but  basically just 
transaction.enter_transaction_management() then 
transaction.managed(True) before and 
transaction.leave_transaction_management() after - the latter will 
rollback and raise an error if you forgot to commit or rollback, and 
remember to commit and rollback as necessary during your stuff.


This is useful to know how to do anyway for complex interactive 
manipulations from the shell you might want to rollback as a whole.


[Loosely related - there is also the autocommit django setting for 
postgresql to consider, I haven't really 100% got my head around all 
ramifications of it yet - this blog post has been very helpful though:


http://thebuild.com/blog/2009/11/07/django-postgresql-and-autocommit/

http://docs.djangoproject.com/en/dev/ref/databases/#autocommit-mode

- note in particular turning it on apparently doesn't preclude sections 
of code being under full transaction management (as the name might 
suggest to some people)]




* say:

current behaviour (which is same as @autocommit),
line-by-line commit on successful line or rollback if the line raises an 
error, a session commit on successful exit, (two conceivably variations 
analogous to @commit_on_success)

full manual management (analogous to @commit_manually)



--
You received this message because you are subscribed to the Google Groups "Django 
users" 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/django-users?hl=en.



Re: How do you rollback a transaction outside the context of a request?

2010-04-15 Thread Bill Freeman
How does this apply when there is no request?  I'm not following you.

Bill

On Thu, Apr 15, 2010 at 4:20 AM, Thomas Guettler  wrote:
> Hi,
>
> here is the way I do it: I use the TransactionMiddleware. Every request gets
> commited or rollbacked (A of ACID (atomar)).
>
> Only methods that are called from the shell (scripts in bin/...) have the 
> commit_on_success decorator.
>
> If methods get used from the shell and from views, they do not use the 
> commit_on_success
> decorator. Only the calling script in bin/ uses this.
>
> I would not use django.db.transaction.rollback() or something. Use the
> available decorators. Maybe you need to restructure your code to
> put the statements which can fail into an new decorated method.
>
> HTH,
>  Thomas
>
> Bill Freeman wrote:
>> I'm running code from the manage.py shell to load stuff (from an XML export 
>> from
>> an excel read of a SQL Server dump, of all things), which gets a database 
>> error
>> (Postgersql correctly noticing that a value is too long for a field,
>> for instance) upon
>> calling the save method of a model.  I'd like to catch the exception, log 
>> about
>> what instance failed, and continue.
>>
>> But now the db connection is within a transaction, which I assume needs to be
>> rolled back, and the connection won't talk to me until I do so.
>>
>> The trouble is, I don't know how.  Just calling 
>> django.db.transaction.rollback()
>> doesn't work, and neither do several other guesses.
>>
>> I presume that the view decorators won't do it since this isn't a request
>> coming through the middleware to a view function.
>>
>> Can someone tell me the appropriate incantations?
>>
>> Bill
>>
>
> --
> Thomas Guettler, http://www.thomas-guettler.de/
> E-Mail: guettli (*) thomas-guettler + de
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Django users" 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/django-users?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" 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/django-users?hl=en.



Re: How do you rollback a transaction outside the context of a request?

2010-04-15 Thread Bill Freeman
Yes.  I saw that in the implementation of django.db.transaction.rollback().
I hesitate to use "private" methods, but since it's an odd requirement, I
may well go this way.

Thanks,
Bill

On Wed, Apr 14, 2010 at 7:25 PM, Joe  wrote:
> On Apr 14, 6:15 pm, Bill Freeman  wrote:
>> I'm running code from the manage.py shell to load stuff (from an XML export 
>> from
>> an excel read of a SQL Server dump, of all things), which gets a database 
>> error
>> (Postgersql correctly noticing that a value is too long for a field,
>> for instance) upon
>> calling the save method of a model.  I'd like to catch the exception, log 
>> about
>> what instance failed, and continue.
>>
>> But now the db connection is within a transaction, which I assume needs to be
>> rolled back, and the connection won't talk to me until I do so.
>>
>> The trouble is, I don't know how.  Just calling 
>> django.db.transaction.rollback()
>> doesn't work, and neither do several other guesses.
>>
>> I presume that the view decorators won't do it since this isn't a request
>> coming through the middleware to a view function.
>
> I found this ticket useful for an example of handling DatabaseErrors
> in the shell:
> http://code.djangoproject.com/ticket/10813
>
> Maybe try something like the following?
>
> from django.db import connection, DatabaseError
> try:
>    pass # your code that will throw the error
> except DatabaseError:
>    connection._rollback()
>
>
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Django users" 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/django-users?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" 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/django-users?hl=en.



Re: How do you rollback a transaction outside the context of a request?

2010-04-15 Thread Thomas Guettler
Hi,

here is the way I do it: I use the TransactionMiddleware. Every request gets
commited or rollbacked (A of ACID (atomar)).

Only methods that are called from the shell (scripts in bin/...) have the 
commit_on_success decorator.

If methods get used from the shell and from views, they do not use the 
commit_on_success
decorator. Only the calling script in bin/ uses this.

I would not use django.db.transaction.rollback() or something. Use the
available decorators. Maybe you need to restructure your code to
put the statements which can fail into an new decorated method.

HTH,
  Thomas

Bill Freeman wrote:
> I'm running code from the manage.py shell to load stuff (from an XML export 
> from
> an excel read of a SQL Server dump, of all things), which gets a database 
> error
> (Postgersql correctly noticing that a value is too long for a field,
> for instance) upon
> calling the save method of a model.  I'd like to catch the exception, log 
> about
> what instance failed, and continue.
> 
> But now the db connection is within a transaction, which I assume needs to be
> rolled back, and the connection won't talk to me until I do so.
> 
> The trouble is, I don't know how.  Just calling 
> django.db.transaction.rollback()
> doesn't work, and neither do several other guesses.
> 
> I presume that the view decorators won't do it since this isn't a request
> coming through the middleware to a view function.
> 
> Can someone tell me the appropriate incantations?
> 
> Bill
> 

-- 
Thomas Guettler, http://www.thomas-guettler.de/
E-Mail: guettli (*) thomas-guettler + de

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" 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/django-users?hl=en.



Re: How do you rollback a transaction outside the context of a request?

2010-04-14 Thread Joe
On Apr 14, 6:15 pm, Bill Freeman  wrote:
> I'm running code from the manage.py shell to load stuff (from an XML export 
> from
> an excel read of a SQL Server dump, of all things), which gets a database 
> error
> (Postgersql correctly noticing that a value is too long for a field,
> for instance) upon
> calling the save method of a model.  I'd like to catch the exception, log 
> about
> what instance failed, and continue.
>
> But now the db connection is within a transaction, which I assume needs to be
> rolled back, and the connection won't talk to me until I do so.
>
> The trouble is, I don't know how.  Just calling 
> django.db.transaction.rollback()
> doesn't work, and neither do several other guesses.
>
> I presume that the view decorators won't do it since this isn't a request
> coming through the middleware to a view function.

I found this ticket useful for an example of handling DatabaseErrors
in the shell:
http://code.djangoproject.com/ticket/10813

Maybe try something like the following?

from django.db import connection, DatabaseError
try:
pass # your code that will throw the error
except DatabaseError:
connection._rollback()



-- 
You received this message because you are subscribed to the Google Groups 
"Django users" 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/django-users?hl=en.