title: Does Zend_Db_Adapter::beginTransaction() stack?
body: <p>Consider the following:</p>
  
  <pre><code>/** (Cas_Template_Tree::DeleteNode)
   * Deletes the given node from the tree, and all of it's children.
   *
   * @static
   * @throws Exception
   * @param Cas_Template_Node $node
   * @return void
   */
  public static function DeleteNode(Cas_Template_Node $node)
  {
      $table = new Cas_Table_Templates();
      $adapter = $table-&gt;getAdapter();
      $leftStr = $adapter-&gt;quoteIdentifier('Left');
      $rightStr = $adapter-&gt;quoteIdentifier('Right');
      try
      {
          $adapter-&gt;beginTransaction();
          $row = $table-&gt;find($node-&gt;GetId())-&gt;current();
          $dependantRowSelector = array(
              "$leftStr &gt;= ?" =&gt; $row-&gt;Left,
              "$rightStr &lt;= ?" =&gt; $row-&gt;Right
          );
          //Get the rows removed so that we can nuke the ACLs later.
          $rowsToDelete = $table-&gt;fetchAll($dependantRowSelector)-&gt;toArray();
          //Delete the rows.
          $table-&gt;delete($dependantRowSelector);
          //Delete access control lists on those rows.
          foreach ($rowsToDelete as $rowToDelete)
          {
              Cas_Acl::CreateExisting($rowToDelete['Acl'])-&gt;Delete();
          }
          $left = (int)$row-&gt;Left;
          $right = (int)$row-&gt;Right;
          $difference = $right - $left + 1;
          $table-&gt;update(array('Left' =&gt; new Zend_Db_Expr("$leftStr - $difference")),
                         array("$leftStr &gt; ?" =&gt; $right));
          $table-&gt;update(array('Right' =&gt; new Zend_Db_Expr("$rightStr - $difference")),
                         array("$rightStr &gt; ?" =&gt; $right));
          $adapter-&gt;commit();
      }
      catch (Exception $ex)
      {
          $adapter-&gt;rollBack();
          throw $ex;
      }
  }
  
  /** (Cas_Acl::Delete)
   * Removes this ACL (and all of its dependent access control entries) from the database.
   * @return void
   */
  public function Delete()
  {
      $aclTable = new Cas_Table_AccessControlLists();
      $aceTable = new Cas_Table_AccessControlEntries();
      $adapter = Zend_Db_Table_Abstract::getDefaultAdapter();
      $identifierName = $adapter-&gt;quoteIdentifier('Identifier');
      $aclName = $adapter-&gt;quoteIdentifier('Acl');
      try
      {
          $adapter-&gt;beginTransaction();
          $aceTable-&gt;delete(array("$aclName = ?" =&gt; $this-&gt;GetId()));
          $aclTable-&gt;delete(array("$identifierName = ?" =&gt; $this-&gt;GetId()));
      }
      catch (Exception $ex)
      {
          $adapter-&gt;rollBack();
          throw $ex;
      }
  }
  </code></pre>
  
  <p>Notice how both of these require that transactions work, because otherwise the operation would not be atomic (which would be bad ;) ) However, there are two transaction blocks going on here. The original DeleteNode method calls <code>Cas_Acl::Delete()</code>, which also attempts to execute itself inside of a transaction block. Ideally, Zend_Db would be smart enough to recognize this case, and for this particular call ignore the begin transaction and commit/rollback calls inside <code>Cas_Acl::Delete</code>.</p>
  
  <p>Would the above code be safe? Can it be significantly improved in any way?</p>