1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-18 12:31:17 +02:00

Update FieldtypeMulti::savePageField to use InnoDB transactions when possible, plus add a new shortcut method: WireDatabasePDO::allowTransaction()

This commit is contained in:
Ryan Cramer
2019-09-03 11:49:58 -04:00
parent 38d66af6f1
commit 86695f8499
2 changed files with 39 additions and 10 deletions

View File

@@ -209,7 +209,9 @@ abstract class FieldtypeMulti extends Fieldtype {
if(!$page->id || !$field->id) return false;
/** @var WireDatabasePDO $database */
$database = $this->wire('database');
$useTransaction = $database->allowTransaction();
$values = $page->get($field->name);
$schema = array();
@@ -228,10 +230,18 @@ abstract class FieldtypeMulti extends Fieldtype {
$table = $database->escapeTable($field->table);
$page_id = (int) $page->id;
// since we don't manage IDs of existing values for multi fields, we delete the existing data and insert all of it again
$query = $database->prepare("DELETE FROM `$table` WHERE pages_id=:page_id"); // QA
$query->bindValue(":page_id", $page_id, \PDO::PARAM_INT);
$query->execute();
// use transaction when possible
if($useTransaction) $database->beginTransaction();
try {
// since we don't manage IDs of existing values for multi fields, we delete the existing data and insert all of it again
$query = $database->prepare("DELETE FROM `$table` WHERE pages_id=:page_id"); // QA
$query->bindValue(":page_id", $page_id, \PDO::PARAM_INT);
$query->execute();
} catch(\Exception $e) {
if($useTransaction) $database->rollBack();
throw $e;
}
if(count($values)) {
@@ -284,21 +294,24 @@ abstract class FieldtypeMulti extends Fieldtype {
$sort++;
}
$sql = rtrim($sql, ", ");
$query = $database->prepare($sql);
try {
$query = $database->prepare(rtrim($sql, ", "));
$result = $query->execute();
} catch(\Exception $e) {
if($useTransaction) $database->rollBack();
if($this->wire('config')->allowExceptions) throw $e; // throw original
$msg = $e->getMessage();
if($this->wire('config')->debug && $this->wire('config')->advanced) $msg .= "\n$sql";
throw new WireException($msg); // throw WireException
}
return $result;
} else {
$result = true;
}
return true;
if($useTransaction) $database->commit();
return $result;
}
/**

View File

@@ -332,7 +332,7 @@ class WireDatabasePDO extends Wire implements WireDatabase {
*
*/
public function inTransaction() {
return $this->pdo()->inTransaction();
return (bool) $this->pdo()->inTransaction();
}
/**
@@ -361,6 +361,22 @@ class WireDatabasePDO extends Wire implements WireDatabase {
return strtoupper($engine) === 'INNODB';
}
/**
* Allow a new transaction to begin right now? (i.e. supported and not already in one)
*
* Returns combined result of supportsTransaction() === true and inTransaction() === false.
*
* #pw-group-PDO
*
* @param string $table Optional table that transaction will be for
* @return bool
* @since 3.0.140
*
*/
public function allowTransaction($table = '') {
return $this->supportsTransaction($table) && !$this->inTransaction();
}
/**
* Commits a transaction
*