MDL-43761 execute bulk sql when modifying db structure

In case of postgresql this uses transactions to allow easier recovery from broken installs.
This commit is contained in:
Petr Škoda 2014-01-24 13:47:22 +08:00
parent ab3fc898f4
commit b4b03d38b7
2 changed files with 34 additions and 12 deletions

View File

@ -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;
}

View File

@ -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;
}