]> begriffs open source - ai-pg/blob - full-docs/src/sgml/html/pltcl-subtransactions.html
PG 18 docs from https://ftp.postgresql.org/pub/source/v18.0/postgresql-18.0-docs...
[ai-pg] / full-docs / src / sgml / html / pltcl-subtransactions.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>42.9. Explicit Subtransactions in PL/Tcl</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="pltcl-error-handling.html" title="42.8. Error Handling in PL/Tcl" /><link rel="next" href="pltcl-transactions.html" title="42.10. 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">42.9. Explicit Subtransactions in PL/Tcl</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="pltcl-error-handling.html" title="42.8. Error Handling in PL/Tcl">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="pltcl.html" title="Chapter 42. PL/Tcl — Tcl Procedural Language">Up</a></td><th width="60%" align="center">Chapter 42. PL/Tcl — Tcl 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="pltcl-transactions.html" title="42.10. Transaction Management">Next</a></td></tr></table><hr /></div><div class="sect1" id="PLTCL-SUBTRANSACTIONS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">42.9. Explicit Subtransactions in PL/Tcl <a href="#PLTCL-SUBTRANSACTIONS" class="id_link">#</a></h2></div></div></div><a id="id-1.8.9.13.2" class="indexterm"></a><p>
3      Recovering from errors caused by database access as described in
4      <a class="xref" href="pltcl-error-handling.html" title="42.8. Error Handling in PL/Tcl">Section 42.8</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/Tcl offers a solution to this problem in
8      the form of explicit subtransactions.
9     </p><p>
10      Consider a function that implements a transfer between two accounts:
11 </p><pre class="programlisting">
12 CREATE FUNCTION transfer_funds() RETURNS void AS $$
13     if [catch {
14         spi_exec "UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'"
15         spi_exec "UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'"
16     } errormsg] {
17         set result [format "error transferring funds: %s" $errormsg]
18     } else {
19         set result "funds transferred successfully"
20     }
21     spi_exec "INSERT INTO operations (result) VALUES ('[quote $result]')"
22 $$ LANGUAGE pltcl;
23 </pre><p>
24      If the second <code class="command">UPDATE</code> statement results in an
25      exception being raised, this function will log the failure, but
26      the result of the first <code class="command">UPDATE</code> will
27      nevertheless be committed.  In other words, the funds will be
28      withdrawn from Joe's account, but will not be transferred to
29      Mary's account.  This happens because each <code class="function">spi_exec</code>
30      is a separate subtransaction, and only one of those subtransactions
31      got rolled back.
32     </p><p>
33      To handle such cases, you can wrap multiple database operations in an
34      explicit subtransaction, which will succeed or roll back as a whole.
35      PL/Tcl provides a <code class="function">subtransaction</code> command to manage
36      this.  We can rewrite our function as:
37 </p><pre class="programlisting">
38 CREATE FUNCTION transfer_funds2() RETURNS void AS $$
39     if [catch {
40         subtransaction {
41             spi_exec "UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'"
42             spi_exec "UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'"
43         }
44     } errormsg] {
45         set result [format "error transferring funds: %s" $errormsg]
46     } else {
47         set result "funds transferred successfully"
48     }
49     spi_exec "INSERT INTO operations (result) VALUES ('[quote $result]')"
50 $$ LANGUAGE pltcl;
51 </pre><p>
52      Note that use of <code class="function">catch</code> is still required for this
53      purpose.  Otherwise the error would propagate to the top level of the
54      function, preventing the desired insertion into
55      the <code class="structname">operations</code> table.
56      The <code class="function">subtransaction</code> command does not trap errors, it
57      only assures that all database operations executed inside its scope will
58      be rolled back together when an error is reported.
59     </p><p>
60      A rollback of an explicit subtransaction occurs on any error reported
61      by the contained Tcl code, not only errors originating from database
62      access.  Thus a regular Tcl exception raised inside
63      a <code class="function">subtransaction</code> command will also cause the
64      subtransaction to be rolled back.  However, non-error exits out of the
65      contained Tcl code (for instance, due to <code class="function">return</code>) do
66      not cause a rollback.
67     </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="pltcl-error-handling.html" title="42.8. Error Handling in PL/Tcl">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="pltcl.html" title="Chapter 42. PL/Tcl — Tcl Procedural Language">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="pltcl-transactions.html" title="42.10. Transaction Management">Next</a></td></tr><tr><td width="40%" align="left" valign="top">42.8. Error Handling in PL/Tcl </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"> 42.10. Transaction Management</td></tr></table></div></body></html>