diff --git a/cake/libs/model/cake_schema.php b/cake/libs/model/cake_schema.php index f72d148b9..ae745c76e 100644 --- a/cake/libs/model/cake_schema.php +++ b/cake/libs/model/cake_schema.php @@ -465,6 +465,7 @@ class CakeSchema extends Object { $tables[$table]['drop'] = $diff; } } + foreach ($fields as $field => $value) { if (isset($old[$table][$field])) { $diff = array_diff_assoc($value, $old[$table][$field]); diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index dc41588b4..a0135e5d3 100755 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -1658,6 +1658,22 @@ class DboSource extends DataSource { } elseif ($conditions === null) { $conditions = $this->conditions($this->defaultConditions($model, $conditions, false), true, true, $model); } else { + $noJoin = true; + foreach ($conditions as $field => $value) { + $originalField = $field; + if (strpos($field, '.') !== false) { + list($alias, $field) = explode('.', $field); + } + if (!$model->hasField($field)) { + $noJoin = false; + break; + } + $conditions[$field] = $value; + unset($conditions[$originalField]); + } + if ($noJoin === true) { + return $this->conditions($conditions); + } $idList = $model->find('all', array( 'fields' => "{$model->alias}.{$model->primaryKey}", 'conditions' => $conditions diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 0950afdeb..c1de0d85b 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -1429,10 +1429,12 @@ class Model extends Overloadable { } if ($this->hasAndBelongsToMany[$assoc]['unique']) { - $conditions = array_merge( - array($join . '.' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] => $id), - (array)$this->hasAndBelongsToMany[$assoc]['conditions'] + $conditions = array( + $join . '.' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] => $id ); + if (!empty($this->hasAndBelongsToMany[$assoc]['conditions'])) { + $conditions = array_merge($conditions, (array)$this->hasAndBelongsToMany[$assoc]['conditions']); + } $links = $this->{$join}->find('all', array( 'conditions' => $conditions, 'recursive' => empty($this->hasAndBelongsToMany[$assoc]['conditions']) ? -1 : 0, @@ -1456,7 +1458,7 @@ class Model extends Overloadable { } if (!empty($newValues)) { - $fields = implode(',', $fields); + $fields = implode(',', $fields); $db->insertMulti($this->{$join}, $fields, $newValues); } } diff --git a/cake/libs/set.php b/cake/libs/set.php index 516570bab..2042c6fc1 100644 --- a/cake/libs/set.php +++ b/cake/libs/set.php @@ -936,6 +936,9 @@ class Set { } else { $keys = Set::extract($data, $path1); } + if (empty($keys)) { + return array(); + } if (!empty($path2) && is_array($path2)) { $format = array_shift($path2); @@ -967,7 +970,9 @@ class Set { return $out; } } - + if (empty($vals)) { + return array(); + } return array_combine($keys, $vals); } diff --git a/cake/tests/cases/libs/model/behaviors/containable.test.php b/cake/tests/cases/libs/model/behaviors/containable.test.php index 9305a2060..898747b02 100644 --- a/cake/tests/cases/libs/model/behaviors/containable.test.php +++ b/cake/tests/cases/libs/model/behaviors/containable.test.php @@ -3352,6 +3352,7 @@ class ContainableBehaviorTest extends CakeTestCase { $this->assertTrue(empty($this->Article->hasMany['ArticlesTag'])); } + /** * testResetAssociation method * diff --git a/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php b/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php index 4c1bb7ded..28f9d7338 100644 --- a/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php @@ -166,8 +166,8 @@ class DboPostgresTest extends CakeTestCase { * @access public */ var $fixtures = array('core.user', 'core.binary_test', 'core.comment', 'core.article', - 'core.tag', 'core.articles_tag', 'core.attachment', 'core.person', 'core.post', 'core.author'); - + 'core.tag', 'core.articles_tag', 'core.attachment', 'core.person', 'core.post', 'core.author', + ); /** * Actual DB connection used in testing * @@ -503,16 +503,23 @@ class DboPostgresTest extends CakeTestCase { )'); $model =& ClassRegistry::init('datatypes'); $schema = new CakeSchema(array('connection' => 'test_suite')); - $result = $schema->read(array('connection' => 'test_suite')); - $schema->tables = $result['tables']['missing']; + $result = $schema->read(array( + 'connection' => 'test_suite', + 'models' => array('Datatype') + )); + $schema->tables = array('datatypes' => $result['tables']['datatypes']); $result = $db1->createSchema($schema, 'datatypes'); $this->assertNoPattern('/timestamp DEFAULT/', $result); $this->assertPattern('/timestamp\s*,/', $result); $db1->query('DROP TABLE ' . $db1->fullTableName('datatypes')); + $db1->query($result); - $result2 = $schema->read(array('connection' => 'test_suite')); - $schema->tables = $result2['tables']['missing']; + $result2 = $schema->read(array( + 'connection' => 'test_suite', + 'models' => array('Datatype') + )); + $schema->tables = array('datatypes' => $result2['tables']['datatypes']); $result2 = $db1->createSchema($schema, 'datatypes'); $this->assertEqual($result, $result2); diff --git a/cake/tests/cases/libs/model/model_delete.test.php b/cake/tests/cases/libs/model/model_delete.test.php index fe69d9c95..6a3b75797 100644 --- a/cake/tests/cases/libs/model/model_delete.test.php +++ b/cake/tests/cases/libs/model/model_delete.test.php @@ -618,6 +618,7 @@ class ModelDeleteTest extends BaseModelTest { )); $this->assertEqual($result['Monkey'], $expected); } + /** * test that beforeDelete returning false can abort deletion. * @@ -634,6 +635,62 @@ class ModelDeleteTest extends BaseModelTest { $exists = $Model->findById(1); $this->assertTrue(is_array($exists)); } + +/** + * test for a habtm deletion error that occurs in postgres but should not. + * And should not occur in any dbo. + * + * @return void + */ + function testDeleteHabtmPostgresFailure() { + $this->loadFixtures('Article', 'Tag', 'ArticlesTag'); + + $Article =& ClassRegistry::init('Article'); + $Article->hasAndBelongsToMany['Tag']['unique'] = true; + + $Tag =& ClassRegistry::init('Tag'); + $Tag->bindModel(array('hasAndBelongsToMany' => array( + 'Article' => array( + 'className' => 'Article', + 'unique' => true + ) + )), true); + + // Article 1 should have Tag.1 and Tag.2 + $before = $Article->find("all", array( + "conditions" => array("Article.id" => 1), + )); + $this->assertEqual(count($before[0]['Tag']), 2, 'Tag count for Article.id = 1 is incorrect, should be 2 %s'); + + // From now on, Tag #1 is only associated with Post #1 + $submitted_data = array( + "Tag" => array("id" => 1, 'tag' => 'tag1'), + "Article" => array( + "Article" => array(1) + ) + ); + $Tag->save($submitted_data); + + // One more submission (The other way around) to make sure the reverse save looks good. + $submitted_data = array( + "Article" => array("id" => 2, 'title' => 'second article'), + "Tag" => array( + "Tag" => array(2, 3) + ) + ); + // ERROR: + // Postgresql: DELETE FROM "articles_tags" WHERE tag_id IN ('1', '3') + // MySQL: DELETE `ArticlesTag` FROM `articles_tags` AS `ArticlesTag` WHERE `ArticlesTag`.`article_id` = 2 AND `ArticlesTag`.`tag_id` IN (1, 3) + $Article->save($submitted_data); + + // Want to make sure Article #1 has Tag #1 and Tag #2 still. + $after = $Article->find("all", array( + "conditions" => array("Article.id" => 1), + )); + + // Removing Article #2 from Tag #1 is all that should have happened. + $this->assertEqual(count($before[0]["Tag"]), count($after[0]["Tag"])); + } } ?> \ No newline at end of file diff --git a/cake/tests/cases/libs/model/model_write.test.php b/cake/tests/cases/libs/model/model_write.test.php index ba488403a..dc757d576 100644 --- a/cake/tests/cases/libs/model/model_write.test.php +++ b/cake/tests/cases/libs/model/model_write.test.php @@ -328,6 +328,7 @@ class ModelWriteTest extends BaseModelTest { $data = array( 'OverallFavorite' => array( + 'id' => 22, 'model_type' => '8-track', 'model_id' => '3', 'priority' => '1' @@ -391,6 +392,7 @@ class ModelWriteTest extends BaseModelTest { $User = new CounterCacheUser(); $Post = new CounterCachePost(); $data = array('Post' => array( + 'id' => 22, 'title' => 'New Post', 'user_id' => 66 )); @@ -1611,7 +1613,7 @@ class ModelWriteTest extends BaseModelTest { 'DoomedSomethingElse' => array( 'className' => 'SomethingElse', 'joinTable' => 'join_things', - 'conditions' => 'JoinThing.doomed = 1', + 'conditions' => 'JoinThing.doomed = true', 'unique' => true ), 'NotDoomedSomethingElse' => array( diff --git a/cake/tests/cases/libs/set.test.php b/cake/tests/cases/libs/set.test.php index 3b6018c2e..f09279ea4 100644 --- a/cake/tests/cases/libs/set.test.php +++ b/cake/tests/cases/libs/set.test.php @@ -1653,6 +1653,9 @@ class SetTest extends CakeTestCase { $result = Set::combine($b, 'users.{n}.User.id', 'users.{n}.User.non-existant'); $expected = array(2 => null, 14 => null, 25 => null); $this->assertIdentical($result, $expected); + + $result = Set::combine($a, 'fail', 'fail'); + $this->assertEqual($result, array()); } /**