<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>KennyNet &#187; pdo</title>
	<atom:link href="http://www.kennynet.co.uk/tag/pdo/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kennynet.co.uk</link>
	<description>Ramblings of a PHP developer</description>
	<lastBuildDate>Fri, 02 Dec 2011 14:05:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>PHP, PDO &amp; Nested Transactions</title>
		<link>http://www.kennynet.co.uk/2008/12/02/php-pdo-nested-transactions/</link>
		<comments>http://www.kennynet.co.uk/2008/12/02/php-pdo-nested-transactions/#comments</comments>
		<pubDate>Tue, 02 Dec 2008 13:09:43 +0000</pubDate>
		<dc:creator>Kenny Millington</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[pdo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[transactions]]></category>

		<guid isPermaLink="false">http://www.kennynet.co.uk/?p=38</guid>
		<description><![CDATA[I&#8217;ve been using PDO as my database library and it works reasonably well (as long as you remember it&#8217;s not a full blown database abstraction library), however recently I needed to use nested transactions to ensure that the database remains consistent while doing a series of SQL statements. Unfortunately PDO does not support nested transactions [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using <a href="http://www.php.net/pdo">PDO</a> as my database library and it works reasonably well (as long as you remember it&#8217;s not a full blown database abstraction library), however recently I needed to use nested transactions to ensure that the database remains consistent while doing a series of SQL statements.</p>
<p>Unfortunately PDO does not support nested transactions although <a href="http://www.postgresql.org">PostgreSQL</a> and <a href="http://www.mysql.com">MySQL</a> do. I decided to extend the PDO class to support nested transactions while also using PDO to keep track of the first transaction. I came up with the following class (released under the <a href="http://www.gnu.org/licenses/gpl-3.0-standalone.html">GNU General Public License, Version 3</a>):-</p>
<pre>class MyPDO extends PDO {
    // Database drivers that support SAVEPOINTs.
    protected static $savepointTransactions = array("pgsql", "mysql");

    // The current transaction level.
    protected $transLevel = 0;

    protected function nestable() {
        return in_array($this-&gt;getAttribute(PDO::ATTR_DRIVER_NAME),
                        self::$savepointTransactions);
    }

    public function beginTransaction() {
        if(!$this-&gt;nestable() || $this-&gt;transLevel == 0) {
            parent::beginTransaction();
        } else {
            $this-&gt;exec("SAVEPOINT LEVEL{$this-&gt;transLevel}");
        }

        $this-&gt;transLevel++;
    }

    public function commit() {
        $this-&gt;transLevel--;

        if(!$this-&gt;nestable() || $this-&gt;transLevel == 0) {
            parent::commit();
        } else {
            $this-&gt;exec("RELEASE SAVEPOINT LEVEL{$this-&gt;transLevel}");
        }
    }

    public function rollBack() {
        $this-&gt;transLevel--;

        if(!$this-&gt;nestable() || $this-&gt;transLevel == 0) {
            parent::rollBack();
        } else {
            $this-&gt;exec("ROLLBACK TO SAVEPOINT LEVEL{$this-&gt;transLevel}");
        }
    }
}</pre>
<p>This  code will only attempt to use the SAVEPOINT code if you&#8217;re using a database driver that supports it (it should probably version check the database server) this then means that in your code you can do things like:-</p>
<pre>$pdo = new MyPDO(DB_DSN, DB_USER, DB_PASS);
$pdo-&gt;beginTransaction();
try {
    $pdo-&gt;exec(...);
    $pdo-&gt;exec(...);

    $pdo-&gt;beginTransaction();
    try {
        $pdo-&gt;exec(...);
        $pdo-&gt;exec(...);
        $pdo-&gt;exec(...);
        $pdo-&gt;commit();
    } catch(PDOException $e) {
        // If this statement fails, rollback...
        // NOTE: This will only rollback statements made in the
        //       inner try { block and not the outer one.
        $pdo-&gt;rollBack();
    }

    $pdo-&gt;commit();
} catch (PDOException $e) {
    $pdo-&gt;rollBack();
}</pre>
<p><strong>NB:</strong> I&#8217;ve tweaked the code slightly when transferring it to my blog and I haven&#8217;t tested it, so there could be some minor errors &#8211; please leave comments if you spot any. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kennynet.co.uk/2008/12/02/php-pdo-nested-transactions/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

