Code

Ticket #9206: extra_v3.diff

File extra_v3.diff, 3.8 KB (added by Richard Davies <richard.davies@…>, 5 years ago)

New draft again of extra piece

Line 
1Index: docs/topics/db/transactions.txt
2===================================================================
3--- docs/topics/db/transactions.txt     (revision 10663)
4+++ docs/topics/db/transactions.txt     (working copy)
5@@ -166,28 +166,61 @@
6 
7 .. _information on MySQL transactions: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html
8 
9-Transactions and savepoints in PostgreSQL 8
10-===========================================
11+Database exceptions within PostgreSQL transactions
12+==================================================
13 
14-When a call to a PostgreSQL 8 cursor raises an exception, all subsequent SQL
15-in the same transaction fails with the error "current transaction is aborted,
16-queries ignored until end of transaction block". Whilst simple use of save()
17-is unlikely to raise an exception in PostgreSQL, there are many more advanced
18-usage patterns which might: for example, saving objects with unique fields,
19-saving using the force_insert/force_update flag, or invoking custom SQL.
20+When a call to a PostgreSQL cursor raises an exception (typically
21+``IntegrityError``), all subsequent SQL in the same transaction fails with
22+the error "current transaction is aborted, queries ignored until end of
23+transaction block".  Whilst simple use of save() is unlikely to raise an
24+exception in PostgreSQL, there are many more advanced usage patterns which
25+might: for example, saving objects with unique fields, saving using the
26+force_insert/force_update flag, or invoking custom SQL.  Example::
27 
28-In any of these cases, you can wrap the command which may throw
29-IntegrityError inside savepoints, which will then allow subsequent commands
30-to proceed. Example::
31-
32+    a.save() # succeeds
33     try:
34-      sid = transaction.savepoint()
35-      x.save()
36-      transaction.savepoint_commit(sid)
37-    except IntegrityError:
38-      transaction.savepoint_rollback(sid)
39-      raise
40+      b.save() # throws exception due to unique field
41+    except:
42+      pass
43+    c.save() # fails as current transaction is aborted
44 
45-Savepoints are not implemented in PostgreSQL 7. If you experience an
46-IntegrityError when using PostgreSQL 7, you will need to rollback to the
47-start of the transaction.
48+There are three possible solutions to this issue:
49+
50+    * With any version of PostgreSQL, you can rollback to the start of the
51+      transaction if you experience an exception. Example::
52+
53+          a.save() # succeeds, but may be undone by rollback
54+          try:
55+            b.save() # throws exception due to unique field
56+          except:
57+            transaction.rollback()
58+          c.save() # succeeds
59+
60+      Note that under the ``commit_on_success`` or ``commit_manually``
61+      decorators the rollback will also undo ``a.save()``.
62+
63+    * With PostgreSQL 8 or later, you can wrap just the command which may
64+      raise an exception inside savepoints, isolating the rollback. Example::
65+
66+          a.save() # succeeds, and never undone by savepoint rollback
67+          try:
68+            sid = transaction.savepoint()
69+            b.save() # throws exception due to unique field
70+            transaction.savepoint_commit(sid)
71+          except:
72+            transaction.savepoint_rollback(sid)
73+          c.save() # succeeds
74+
75+    * With PostgreSQL 8.2 or later, there is an advanced option to run
76+      PostgreSQL with :ref:`database-level autocommit <ref-databases>`.
77+      With this option there is no constantly open transaction, so
78+      savepoints are not required to continue after catching an exception.
79+      Please see the documentation for that feature, which behaves
80+      differently from the standard ``autocommit`` decorator. Example::
81+
82+         a.save() # succeeds
83+         try:
84+           b.save() # throws exception due to unique field
85+         except:
86+           pass
87+         c.save() # succeeds