~ubuntu-branches/debian/sid/postgresql-9.3/sid

« back to all changes in this revision

Viewing changes to doc/src/sgml/html/plpython-subtransaction.html

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-05-08 05:39:52 UTC
  • Revision ID: package-import@ubuntu.com-20130508053952-1j7uilp7mjtrvq8q
Tags: upstream-9.3~beta1
ImportĀ upstreamĀ versionĀ 9.3~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 
2
<HTML
 
3
><HEAD
 
4
><TITLE
 
5
>Explicit Subtransactions</TITLE
 
6
><META
 
7
NAME="GENERATOR"
 
8
CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
 
9
REV="MADE"
 
10
HREF="mailto:pgsql-docs@postgresql.org"><LINK
 
11
REL="HOME"
 
12
TITLE="PostgreSQL 9.3beta1 Documentation"
 
13
HREF="index.html"><LINK
 
14
REL="UP"
 
15
TITLE="PL/Python - Python Procedural Language"
 
16
HREF="plpython.html"><LINK
 
17
REL="PREVIOUS"
 
18
TITLE="Database Access"
 
19
HREF="plpython-database.html"><LINK
 
20
REL="NEXT"
 
21
TITLE="Utility Functions"
 
22
HREF="plpython-util.html"><LINK
 
23
REL="STYLESHEET"
 
24
TYPE="text/css"
 
25
HREF="stylesheet.css"><META
 
26
HTTP-EQUIV="Content-Type"
 
27
CONTENT="text/html; charset=ISO-8859-1"><META
 
28
NAME="creation"
 
29
CONTENT="2013-05-06T21:00:50"></HEAD
 
30
><BODY
 
31
CLASS="SECT1"
 
32
><DIV
 
33
CLASS="NAVHEADER"
 
34
><TABLE
 
35
SUMMARY="Header navigation table"
 
36
WIDTH="100%"
 
37
BORDER="0"
 
38
CELLPADDING="0"
 
39
CELLSPACING="0"
 
40
><TR
 
41
><TH
 
42
COLSPAN="5"
 
43
ALIGN="center"
 
44
VALIGN="bottom"
 
45
><A
 
46
HREF="index.html"
 
47
>PostgreSQL 9.3beta1 Documentation</A
 
48
></TH
 
49
></TR
 
50
><TR
 
51
><TD
 
52
WIDTH="10%"
 
53
ALIGN="left"
 
54
VALIGN="top"
 
55
><A
 
56
TITLE="Database Access"
 
57
HREF="plpython-database.html"
 
58
ACCESSKEY="P"
 
59
>Prev</A
 
60
></TD
 
61
><TD
 
62
WIDTH="10%"
 
63
ALIGN="left"
 
64
VALIGN="top"
 
65
><A
 
66
HREF="plpython.html"
 
67
ACCESSKEY="U"
 
68
>Up</A
 
69
></TD
 
70
><TD
 
71
WIDTH="60%"
 
72
ALIGN="center"
 
73
VALIGN="bottom"
 
74
>Chapter 43. PL/Python - Python Procedural Language</TD
 
75
><TD
 
76
WIDTH="20%"
 
77
ALIGN="right"
 
78
VALIGN="top"
 
79
><A
 
80
TITLE="Utility Functions"
 
81
HREF="plpython-util.html"
 
82
ACCESSKEY="N"
 
83
>Next</A
 
84
></TD
 
85
></TR
 
86
></TABLE
 
87
><HR
 
88
ALIGN="LEFT"
 
89
WIDTH="100%"></DIV
 
90
><DIV
 
91
CLASS="SECT1"
 
92
><H1
 
93
CLASS="SECT1"
 
94
><A
 
95
NAME="PLPYTHON-SUBTRANSACTION"
 
96
>43.8. Explicit Subtransactions</A
 
97
></H1
 
98
><P
 
99
>   Recovering from errors caused by database access as described in
 
100
   <A
 
101
HREF="plpython-database.html#PLPYTHON-TRAPPING"
 
102
>Section 43.7.2</A
 
103
> can lead to an undesirable
 
104
   situation where some operations succeed before one of them fails,
 
105
   and after recovering from that error the data is left in an
 
106
   inconsistent state.  PL/Python offers a solution to this problem in
 
107
   the form of explicit subtransactions.
 
108
  </P
 
109
><DIV
 
110
CLASS="SECT2"
 
111
><H2
 
112
CLASS="SECT2"
 
113
><A
 
114
NAME="AEN61058"
 
115
>43.8.1. Subtransaction Context Managers</A
 
116
></H2
 
117
><P
 
118
>    Consider a function that implements a transfer between two
 
119
    accounts:
 
120
</P><PRE
 
121
CLASS="PROGRAMLISTING"
 
122
>CREATE FUNCTION transfer_funds() RETURNS void AS $$
 
123
try:
 
124
    plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'")
 
125
    plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'")
 
126
except plpy.SPIError, e:
 
127
    result = "error transferring funds: %s" % e.args
 
128
else:
 
129
    result = "funds transferred correctly"
 
130
plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
 
131
plpy.execute(plan, [result])
 
132
$$ LANGUAGE plpythonu;</PRE
 
133
><P>
 
134
    If the second <TT
 
135
CLASS="LITERAL"
 
136
>UPDATE</TT
 
137
> statement results in an
 
138
    exception being raised, this function will report the error, but
 
139
    the result of the first <TT
 
140
CLASS="LITERAL"
 
141
>UPDATE</TT
 
142
> will
 
143
    nevertheless be committed.  In other words, the funds will be
 
144
    withdrawn from Joe's account, but will not be transferred to
 
145
    Mary's account.
 
146
   </P
 
147
><P
 
148
>    To avoid such issues, you can wrap your
 
149
    <TT
 
150
CLASS="LITERAL"
 
151
>plpy.execute</TT
 
152
> calls in an explicit
 
153
    subtransaction.  The <TT
 
154
CLASS="LITERAL"
 
155
>plpy</TT
 
156
> module provides a
 
157
    helper object to manage explicit subtransactions that gets created
 
158
    with the <TT
 
159
CLASS="LITERAL"
 
160
>plpy.subtransaction()</TT
 
161
> function.
 
162
    Objects created by this function implement the
 
163
    <A
 
164
HREF="http://docs.python.org/library/stdtypes.html#context-manager-types"
 
165
TARGET="_top"
 
166
>    context manager interface</A
 
167
>.  Using explicit subtransactions
 
168
    we can rewrite our function as:
 
169
</P><PRE
 
170
CLASS="PROGRAMLISTING"
 
171
>CREATE FUNCTION transfer_funds2() RETURNS void AS $$
 
172
try:
 
173
    with plpy.subtransaction():
 
174
        plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'")
 
175
        plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'")
 
176
except plpy.SPIError, e:
 
177
    result = "error transferring funds: %s" % e.args
 
178
else:
 
179
    result = "funds transferred correctly"
 
180
plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
 
181
plpy.execute(plan, [result])
 
182
$$ LANGUAGE plpythonu;</PRE
 
183
><P>
 
184
    Note that the use of <TT
 
185
CLASS="LITERAL"
 
186
>try/catch</TT
 
187
> is still
 
188
    required.  Otherwise the exception would propagate to the top of
 
189
    the Python stack and would cause the whole function to abort with
 
190
    a <SPAN
 
191
CLASS="PRODUCTNAME"
 
192
>PostgreSQL</SPAN
 
193
> error, so that the
 
194
    <TT
 
195
CLASS="LITERAL"
 
196
>operations</TT
 
197
> table would not have any row
 
198
    inserted into it.  The subtransaction context manager does not
 
199
    trap errors, it only assures that all database operations executed
 
200
    inside its scope will be atomically committed or rolled back.  A
 
201
    rollback of the subtransaction block occurs on any kind of
 
202
    exception exit, not only ones caused by errors originating from
 
203
    database access.  A regular Python exception raised inside an
 
204
    explicit subtransaction block would also cause the subtransaction
 
205
    to be rolled back.
 
206
   </P
 
207
></DIV
 
208
><DIV
 
209
CLASS="SECT2"
 
210
><H2
 
211
CLASS="SECT2"
 
212
><A
 
213
NAME="AEN61073"
 
214
>43.8.2. Older Python Versions</A
 
215
></H2
 
216
><P
 
217
>    Context managers syntax using the <TT
 
218
CLASS="LITERAL"
 
219
>with</TT
 
220
> keyword
 
221
    is available by default in Python 2.6.  If using PL/Python with an
 
222
    older Python version, it is still possible to use explicit
 
223
    subtransactions, although not as transparently.  You can call the
 
224
    subtransaction manager's <TT
 
225
CLASS="LITERAL"
 
226
>__enter__</TT
 
227
> and
 
228
    <TT
 
229
CLASS="LITERAL"
 
230
>__exit__</TT
 
231
> functions using the
 
232
    <TT
 
233
CLASS="LITERAL"
 
234
>enter</TT
 
235
> and <TT
 
236
CLASS="LITERAL"
 
237
>exit</TT
 
238
> convenience
 
239
    aliases.  The example function that transfers funds could be
 
240
    written as:
 
241
</P><PRE
 
242
CLASS="PROGRAMLISTING"
 
243
>CREATE FUNCTION transfer_funds_old() RETURNS void AS $$
 
244
try:
 
245
    subxact = plpy.subtransaction()
 
246
    subxact.enter()
 
247
    try:
 
248
        plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'")
 
249
        plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'")
 
250
    except:
 
251
        import sys
 
252
        subxact.exit(*sys.exc_info())
 
253
        raise
 
254
    else:
 
255
        subxact.exit(None, None, None)
 
256
except plpy.SPIError, e:
 
257
    result = "error transferring funds: %s" % e.args
 
258
else:
 
259
    result = "funds transferred correctly"
 
260
 
 
261
plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
 
262
plpy.execute(plan, [result])
 
263
$$ LANGUAGE plpythonu;</PRE
 
264
><P>
 
265
   </P
 
266
><DIV
 
267
CLASS="NOTE"
 
268
><BLOCKQUOTE
 
269
CLASS="NOTE"
 
270
><P
 
271
><B
 
272
>Note: </B
 
273
>     Although context managers were implemented in Python 2.5, to use
 
274
     the <TT
 
275
CLASS="LITERAL"
 
276
>with</TT
 
277
> syntax in that version you need to
 
278
     use a <A
 
279
HREF="http://docs.python.org/release/2.5/ref/future.html"
 
280
TARGET="_top"
 
281
>future
 
282
     statement</A
 
283
>.  Because of implementation details, however,
 
284
     you cannot use future statements in PL/Python functions.
 
285
    </P
 
286
></BLOCKQUOTE
 
287
></DIV
 
288
></DIV
 
289
></DIV
 
290
><DIV
 
291
CLASS="NAVFOOTER"
 
292
><HR
 
293
ALIGN="LEFT"
 
294
WIDTH="100%"><TABLE
 
295
SUMMARY="Footer navigation table"
 
296
WIDTH="100%"
 
297
BORDER="0"
 
298
CELLPADDING="0"
 
299
CELLSPACING="0"
 
300
><TR
 
301
><TD
 
302
WIDTH="33%"
 
303
ALIGN="left"
 
304
VALIGN="top"
 
305
><A
 
306
HREF="plpython-database.html"
 
307
ACCESSKEY="P"
 
308
>Prev</A
 
309
></TD
 
310
><TD
 
311
WIDTH="34%"
 
312
ALIGN="center"
 
313
VALIGN="top"
 
314
><A
 
315
HREF="index.html"
 
316
ACCESSKEY="H"
 
317
>Home</A
 
318
></TD
 
319
><TD
 
320
WIDTH="33%"
 
321
ALIGN="right"
 
322
VALIGN="top"
 
323
><A
 
324
HREF="plpython-util.html"
 
325
ACCESSKEY="N"
 
326
>Next</A
 
327
></TD
 
328
></TR
 
329
><TR
 
330
><TD
 
331
WIDTH="33%"
 
332
ALIGN="left"
 
333
VALIGN="top"
 
334
>Database Access</TD
 
335
><TD
 
336
WIDTH="34%"
 
337
ALIGN="center"
 
338
VALIGN="top"
 
339
><A
 
340
HREF="plpython.html"
 
341
ACCESSKEY="U"
 
342
>Up</A
 
343
></TD
 
344
><TD
 
345
WIDTH="33%"
 
346
ALIGN="right"
 
347
VALIGN="top"
 
348
>Utility Functions</TD
 
349
></TR
 
350
></TABLE
 
351
></DIV
 
352
></BODY
 
353
></HTML
 
354
>
 
 
b'\\ No newline at end of file'