Skip to content
Permalink
Browse files

Backport changes from #3959 to 1.3

Backport race condition fixes from 2.x to 1.3. This is a severe enough
issue that it warrants a fix.

Refs #3857
  • Loading branch information...
markstory committed Jul 14, 2014
1 parent 319fcbf commit 41082b12124644f048a29d627675316d3e3787c0
@@ -1879,7 +1879,7 @@ function defaultConditions(&$model, $conditions, $useAlias = true) {
return $conditions;
}
$exists = $model->exists();
if (!$exists && $conditions !== null) {
if (!$exists && ($conditions !== null || !empty($model->__safeUpdateMode))) {
return false;
} elseif (!$exists) {
return null;
@@ -357,6 +357,15 @@ class Model extends Overloadable {
*/
var $__affectedRows = null;
/**
* Safe update mode
*
* If true, this prevents Model::save() from generating a query with WHERE 1 = 1 on race condition.
*
* @var bool
*/
var $__safeUpdateMode = false;
/**
* List of valid finder method options, supplied as the first parameter to find().
*
@@ -1324,7 +1333,9 @@ function save($data = null, $validate = true, $fieldList = array()) {
$cache = $this->_prepareUpdateFields(array_combine($fields, $values));
if (!empty($this->id)) {
$this->__safeUpdateMode = true;
$success = (bool)$db->update($this, $fields, $values);
$this->__safeUpdateMode = false;
} else {
$fInfo = $this->_schema[$this->primaryKey];
$isUUID = ($fInfo['length'] == 36 &&
@@ -4675,4 +4675,46 @@ function testFieldsUsingMethodCache() {
$this->testDb->fields($Article, null, array('title', 'body', 'published'));
$this->assertTrue(empty($this->testDb->methodCache['fields']), 'Cache not empty');
}
/**
* Test defaultConditions()
*
* @return void
*/
public function testDefaultConditions() {
$this->loadFixtures('Article');
$Article = ClassRegistry::init('Article');
$db = $Article->getDataSource();
// Creates a default set of conditions from the model if $conditions is null/empty.
$Article->id = 1;
$result = $db->defaultConditions($Article, null);
$this->assertEqual(array('Article.id' => 1), $result);
// $useAlias == false
$Article->id = 1;
$result = $db->defaultConditions($Article, null, false);
$this->assertEqual(array($db->fullTableName($Article, false) . '.id' => 1), $result);
// If conditions are supplied then they will be returned.
$Article->id = 1;
$result = $db->defaultConditions($Article, array('Article.title' => 'First article'));
$this->assertEqual(array('Article.title' => 'First article'), $result);
// If a model doesn't exist and no conditions were provided either null or false will be returned based on what was input.
$Article->id = 1000000;
$result = $db->defaultConditions($Article, null);
$this->assertNull($result);
$Article->id = 1000000;
$result = $db->defaultConditions($Article, false);
$this->assertFalse($result);
// Safe update mode
$Article->id = 1000000;
$Article->__safeUpdateMode = true;
$result = $db->defaultConditions($Article, null);
$this->assertFalse($result);
}
}

0 comments on commit 41082b1

Please sign in to comment.
You can’t perform that action at this time.