Permalink
Browse files

Adding tests from 'Stephen Cuppert' to test incorrectly generate DELE…

…TE queries for habtm join tables that do not have a primary key when using PostgreSQL. Updating DboSource::_matchRecords() to only query the table if the supplied conditions are actually multi-table conditions. Fixes #459
  • Loading branch information...
1 parent 190066f commit ea64588a814b09565b82c428845f7a096814c327 @markstory markstory committed Mar 16, 2010
Showing with 71 additions and 0 deletions.
  1. +16 −0 cake/libs/model/datasources/dbo_source.php
  2. +55 −0 cake/tests/cases/libs/model/model_delete.test.php
@@ -1477,6 +1477,22 @@ function _matchRecords(&$model, $conditions = null) {
} 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
@@ -580,6 +580,61 @@ function testBeforeDeleteDeleteAbortion() {
$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"]));
+ }
}
?>

0 comments on commit ea64588

Please sign in to comment.