diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php index ff6ab53444f..5d2765786d2 100644 --- a/lib/dml/mysqli_native_moodle_database.php +++ b/lib/dml/mysqli_native_moodle_database.php @@ -37,6 +37,7 @@ require_once(__DIR__.'/mysqli_native_moodle_temptables.php'); */ class mysqli_native_moodle_database extends moodle_database { + /** @var mysqli $mysqli */ protected $mysqli = null; private $transactions_supported = null; @@ -827,15 +828,27 @@ class mysqli_native_moodle_database extends moodle_database { */ public function change_database_structure($sql) { $this->get_manager(); // Includes DDL exceptions classes ;-) - $sqls = (array)$sql; + if (is_array($sql)) { + $sql = implode("\n;\n", $sql); + } try { - foreach ($sqls as $sql) { - $this->query_start($sql, null, SQL_QUERY_STRUCTURE); - $result = $this->mysqli->query($sql); - $this->query_end($result); + $this->query_start($sql, null, SQL_QUERY_STRUCTURE); + $result = $this->mysqli->multi_query($sql); + if ($result === false) { + $this->query_end(false); } + while ($this->mysqli->more_results()) { + $result = $this->mysqli->next_result(); + if ($result === false) { + $this->query_end(false); + } + } + $this->query_end(true); } catch (ddl_change_structure_exception $e) { + while (@$this->mysqli->more_results()) { + @$this->mysqli->next_result(); + } $this->reset_caches(); throw $e; } diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index b87286117ca..b0b6552ed04 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -37,6 +37,7 @@ require_once(__DIR__.'/pgsql_native_moodle_temptables.php'); */ class pgsql_native_moodle_database extends moodle_database { + /** @var resource $pgsql database resource */ protected $pgsql = null; protected $bytea_oid = null; @@ -631,16 +632,24 @@ class pgsql_native_moodle_database extends moodle_database { */ public function change_database_structure($sql) { $this->get_manager(); // Includes DDL exceptions classes ;-) - $sqls = (array)$sql; + if (is_array($sql)) { + $sql = implode("\n;\n", $sql); + } + if (!$this->is_transaction_started()) { + // It is better to do all or nothing, this helps with recovery... + $sql = "BEGIN ISOLATION LEVEL SERIALIZABLE;\n$sql\n; COMMIT"; + } try { - foreach ($sqls as $sql) { - $this->query_start($sql, null, SQL_QUERY_STRUCTURE); - $result = pg_query($this->pgsql, $sql); - $this->query_end($result); - pg_free_result($result); - } + $this->query_start($sql, null, SQL_QUERY_STRUCTURE); + $result = pg_query($this->pgsql, $sql); + $this->query_end($result); + pg_free_result($result); } catch (ddl_change_structure_exception $e) { + if (!$this->is_transaction_started()) { + $result = @pg_query($this->pgsql, "ROLLBACK"); + @pg_free_result($result); + } $this->reset_caches(); throw $e; }