]> begriffs open source - ai-pg/blob - full-docs/src/sgml/html/plpython-subtransaction.html
PG 18 docs from https://ftp.postgresql.org/pub/source/v18.0/postgresql-18.0-docs...
[ai-pg] / full-docs / src / sgml / html / plpython-subtransaction.html
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>44.7. Explicit Subtransactions</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="plpython-database.html" title="44.6. Database Access" /><link rel="next" href="plpython-transactions.html" title="44.8. Transaction Management" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">44.7. Explicit Subtransactions</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="plpython-database.html" title="44.6. Database Access">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="plpython.html" title="Chapter 44. PL/Python — Python Procedural Language">Up</a></td><th width="60%" align="center">Chapter 44. PL/Python — Python Procedural Language</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="plpython-transactions.html" title="44.8. Transaction Management">Next</a></td></tr></table><hr /></div><div class="sect1" id="PLPYTHON-SUBTRANSACTION"><div class="titlepage"><div><div><h2 class="title" style="clear: both">44.7. Explicit Subtransactions <a href="#PLPYTHON-SUBTRANSACTION" class="id_link">#</a></h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="plpython-subtransaction.html#PLPYTHON-SUBTRANSACTION-CONTEXT-MANAGERS">44.7.1. Subtransaction Context Managers</a></span></dt></dl></div><p>
3    Recovering from errors caused by database access as described in
4    <a class="xref" href="plpython-database.html#PLPYTHON-TRAPPING" title="44.6.2. Trapping Errors">Section 44.6.2</a> can lead to an undesirable
5    situation where some operations succeed before one of them fails,
6    and after recovering from that error the data is left in an
7    inconsistent state.  PL/Python offers a solution to this problem in
8    the form of explicit subtransactions.
9   </p><div class="sect2" id="PLPYTHON-SUBTRANSACTION-CONTEXT-MANAGERS"><div class="titlepage"><div><div><h3 class="title">44.7.1. Subtransaction Context Managers <a href="#PLPYTHON-SUBTRANSACTION-CONTEXT-MANAGERS" class="id_link">#</a></h3></div></div></div><p>
10     Consider a function that implements a transfer between two
11     accounts:
12 </p><pre class="programlisting">
13 CREATE FUNCTION transfer_funds() RETURNS void AS $$
14 try:
15     plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'")
16     plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'")
17 except plpy.SPIError as e:
18     result = "error transferring funds: %s" % e.args
19 else:
20     result = "funds transferred correctly"
21 plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
22 plpy.execute(plan, [result])
23 $$ LANGUAGE plpython3u;
24 </pre><p>
25     If the second <code class="literal">UPDATE</code> statement results in an
26     exception being raised, this function will report the error, but
27     the result of the first <code class="literal">UPDATE</code> will
28     nevertheless be committed.  In other words, the funds will be
29     withdrawn from Joe's account, but will not be transferred to
30     Mary's account.
31    </p><p>
32     To avoid such issues, you can wrap your
33     <code class="literal">plpy.execute</code> calls in an explicit
34     subtransaction.  The <code class="literal">plpy</code> module provides a
35     helper object to manage explicit subtransactions that gets created
36     with the <code class="literal">plpy.subtransaction()</code> function.
37     Objects created by this function implement the
38     <a class="ulink" href="https://docs.python.org/library/stdtypes.html#context-manager-types" target="_top">
39     context manager interface</a>.  Using explicit subtransactions
40     we can rewrite our function as:
41 </p><pre class="programlisting">
42 CREATE FUNCTION transfer_funds2() RETURNS void AS $$
43 try:
44     with plpy.subtransaction():
45         plpy.execute("UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'")
46         plpy.execute("UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'")
47 except plpy.SPIError as e:
48     result = "error transferring funds: %s" % e.args
49 else:
50     result = "funds transferred correctly"
51 plan = plpy.prepare("INSERT INTO operations (result) VALUES ($1)", ["text"])
52 plpy.execute(plan, [result])
53 $$ LANGUAGE plpython3u;
54 </pre><p>
55     Note that the use of <code class="literal">try</code>/<code class="literal">except</code> is still
56     required.  Otherwise the exception would propagate to the top of
57     the Python stack and would cause the whole function to abort with
58     a <span class="productname">PostgreSQL</span> error, so that the
59     <code class="literal">operations</code> table would not have any row
60     inserted into it.  The subtransaction context manager does not
61     trap errors, it only assures that all database operations executed
62     inside its scope will be atomically committed or rolled back.  A
63     rollback of the subtransaction block occurs on any kind of
64     exception exit, not only ones caused by errors originating from
65     database access.  A regular Python exception raised inside an
66     explicit subtransaction block would also cause the subtransaction
67     to be rolled back.
68    </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="plpython-database.html" title="44.6. Database Access">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="plpython.html" title="Chapter 44. PL/Python — Python Procedural Language">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="plpython-transactions.html" title="44.8. Transaction Management">Next</a></td></tr><tr><td width="40%" align="left" valign="top">44.6. Database Access </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 44.8. Transaction Management</td></tr></table></div></body></html>