Index: modules/simpletest/tests/database_test.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.test,v
retrieving revision 1.110
diff -u -r1.110 database_test.test
--- modules/simpletest/tests/database_test.test	31 Dec 2010 20:43:43 -0000	1.110
+++ modules/simpletest/tests/database_test.test	4 Jan 2011 12:31:55 -0000
@@ -3211,8 +3211,10 @@
    *   Suffix to add to field values to differentiate tests.
    * @param $rollback
    *   Whether or not to try rolling back the transaction when we're done.
+   * @param $ddl_statement
+   *   Whether to execute a DDL statement during the inner transaction.
    */
-  protected function transactionOuterLayer($suffix, $rollback = FALSE) {
+  protected function transactionOuterLayer($suffix, $rollback = FALSE, $ddl_statement = FALSE) {
     $connection = Database::getConnection();
     $depth = $connection->transactionDepth();
     $txn = db_transaction();
@@ -3229,7 +3231,7 @@
 
     // We're already in a transaction, but we call ->transactionInnerLayer
     // to nest another transaction inside the current one.
-    $this->transactionInnerLayer($suffix, $rollback);
+    $this->transactionInnerLayer($suffix, $rollback, $ddl_statement);
 
     $this->assertTrue($connection->inTransaction(), t('In transaction after calling nested transaction.'));
 
@@ -3249,12 +3251,12 @@
    *   Suffix to add to field values to differentiate tests.
    * @param $rollback
    *   Whether or not to try rolling back the transaction when we're done.
+   * @param $ddl_statement
+   *   Whether to execute a DDL statement during the transaction.
    */
-  protected function transactionInnerLayer($suffix, $rollback = FALSE) {
+  protected function transactionInnerLayer($suffix, $rollback = FALSE, $ddl_statement = FALSE) {
     $connection = Database::getConnection();
 
-    $this->assertTrue($connection->inTransaction(), t('In transaction in nested transaction.'));
-
     $depth = $connection->transactionDepth();
     // Start a transaction. If we're being called from ->transactionOuterLayer,
     // then we're already in a transaction. Normally, that would make starting
@@ -3275,6 +3277,22 @@
 
     $this->assertTrue($connection->inTransaction(), t('In transaction inside nested transaction.'));
 
+    if ($ddl_statement) {
+      $table = array(
+        'fields' => array(
+          'id' => array(
+            'type' => 'serial',
+            'unsigned' => TRUE,
+            'not null' => TRUE,
+          ),
+        ),
+        'primary key' => array('id'),
+      );
+      db_create_table('database_test_1', $table);
+
+      $this->assertTrue($connection->inTransaction(), t('In transaction inside nested transaction.'));
+    }
+
     if ($rollback) {
       // Roll back the transaction, if requested.
       // This rollback should propagate to the last savepoint.
@@ -3356,6 +3374,43 @@
       $this->fail($e->getMessage());
     }
   }
+
+  /**
+   * Test the compatibility of transactions with DDL statements.
+   */
+  function testTransactionWithDdlStatement() {
+    // First, test that a commit works normally, even with DDL statements.
+    try {
+      $this->transactionOuterLayer('D', FALSE, TRUE);
+
+      // Because we committed, the inserted rows should both be present.
+      $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DavidD'))->fetchField();
+      $this->assertIdentical($saved_age, '24', t('Can retrieve DavidD row after commit.'));
+      $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DanielD'))->fetchField();
+      $this->assertIdentical($saved_age, '19', t('Can retrieve DanielD row after commit.'));
+      // The created table should also exist.
+      $count = db_query('SELECT COUNT(id) FROM {database_test_1}')->fetchField();
+      $this->assertIdentical($count, '0', t('Table was successfully created inside a transaction.'));
+    }
+    catch (Exception $e) {
+      $this->fail($e->getMessage());
+    }
+
+    // If we rollback the transaction, an exception might be thrown.
+    try {
+      $this->transactionOuterLayer('E', TRUE, TRUE);
+
+      // Because we rolled back, the inserted rows shouldn't be present.
+      $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DavidE'))->fetchField();
+      $this->assertNotIdentical($saved_age, '24', t('Cannot retrieve DavidE row after rollback.'));
+      $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'DanielE'))->fetchField();
+      $this->assertNotIdentical($saved_age, '19', t('Cannot retrieve DanielE row after rollback.'));
+    }
+    catch (Exception $e) {
+      // An exception also lets the test pass.
+      $this->assertTrue(true, t('Exception thrown on rollback after a DDL statement was executed.'));
+    }
+  }
 }
 
 
