diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php index 765f3b7..b7b08f6 100644 --- a/lib/dml/mysqli_native_moodle_database.php +++ b/lib/dml/mysqli_native_moodle_database.php @@ -898,6 +898,12 @@ class mysqli_native_moodle_database extends moodle_database { $sql = implode("\n;\n", $sql); } + if (PHPUNIT_TEST && class_exists('advanced_testcase', false)) { + // Schema changes case an implicit commit, so rollback no longer works, + // see http://dev.mysql.com/doc/refman/5.6/en/implicit-commit.html + advanced_testcase::$preventrollback = true; + } + try { $this->query_start($sql, null, SQL_QUERY_STRUCTURE); $result = $this->mysqli->multi_query($sql); diff --git a/lib/phpunit/classes/advanced_testcase.php b/lib/phpunit/classes/advanced_testcase.php index 12ad693..c0e4f60 100644 --- a/lib/phpunit/classes/advanced_testcase.php +++ b/lib/phpunit/classes/advanced_testcase.php @@ -43,6 +43,15 @@ abstract class advanced_testcase extends PHPUnit_Framework_TestCase { private $currenttimestart; /** + * Added by Moodlerooms - prevent transaction rollback for resetting the DB. + * We want to prevent this in MySQL when something like an alter table happens. + * + * @var bool + * @see http://dev.mysql.com/doc/refman/5.6/en/implicit-commit.html + */ + public static $preventrollback = false; + + /** * Constructs a test case with the given name. * * Note: use setUp() or setUpBeforeClass() in your test cases. @@ -66,11 +75,13 @@ abstract class advanced_testcase extends PHPUnit_Framework_TestCase { final public function runBare() { global $DB; + self::$preventrollback = false; + if (phpunit_util::$lastdbwrites != $DB->perf_get_writes()) { // this happens when previous test does not reset, we can not use transactions $this->testdbtransaction = null; - } else if ($DB->get_dbfamily() === 'postgres' or $DB->get_dbfamily() === 'mssql') { + } else if ($DB->get_dbfamily() === 'postgres' or $DB->get_dbfamily() === 'mssql' or $DB->get_dbfamily() === 'mysql') { // database must allow rollback of DDL, so no mysql here $this->testdbtransaction = $DB->start_delegated_transaction(); } @@ -94,6 +105,9 @@ abstract class advanced_testcase extends PHPUnit_Framework_TestCase { throw $e; } + if (self::$preventrollback) { + $this->preventResetByRollback(); + } if (!$this->testdbtransaction or $this->testdbtransaction->is_disposed()) { $this->testdbtransaction = null; }