diff --git a/lib/Doctrine/Validator/Unique.php b/lib/Doctrine/Validator/Unique.php index e0babf77e..e13cc0e65 100644 --- a/lib/Doctrine/Validator/Unique.php +++ b/lib/Doctrine/Validator/Unique.php @@ -46,10 +46,16 @@ class Doctrine_Validator_Unique $values = array(); $values[] = $value; - - foreach ($table->getPrimaryKeys() as $pk) { - $sql .= " AND {$pk} != ?"; - $values[] = $record->$pk; + + // If the record is not new we need to add primary key checks because its ok if the + // unique value already exists in the database IF the record in the database is the same + // as the one that is validated here. + $state = $record->getState(); + if (! ($state == Doctrine_Record::STATE_TDIRTY || $state == Doctrine_Record::STATE_TCLEAN)) { + foreach ($table->getPrimaryKeys() as $pk) { + $sql .= " AND {$pk} != ?"; + $values[] = $record->$pk; + } } $stmt = $table->getConnection()->getDbh()->prepare($sql); diff --git a/tests/ValidatorTestCase.php b/tests/ValidatorTestCase.php index f79e977d0..3fef92790 100644 --- a/tests/ValidatorTestCase.php +++ b/tests/ValidatorTestCase.php @@ -40,7 +40,7 @@ class Doctrine_Validator_TestCase extends Doctrine_UnitTestCase { $this->tables[] = 'ValidatorTest_FootballPlayer'; parent::prepareTables(); } - + /** * Tests correct type detection. */ @@ -333,7 +333,7 @@ class Doctrine_Validator_TestCase extends Doctrine_UnitTestCase { * * @todo move to a separate test file (tests/Validator/UniqueTestCase) . */ - public function testSetSameUniqueValueThrowsNoException() + public function testSetSameUniqueValueOnSameRecordThrowsNoException() { $this->manager->setAttribute(Doctrine::ATTR_VLD, true); @@ -346,11 +346,33 @@ class Doctrine_Validator_TestCase extends Doctrine_UnitTestCase { try { $r->save(); } - catch(Doctrine_Validator_Exception $e) { + catch (Doctrine_Validator_Exception $e) { $this->fail("Validator exception raised without reason!"); - var_dump($r->getErrorStack()); } + $r->delete(); // clean up + + $this->manager->setAttribute(Doctrine::ATTR_VLD, false); + } + + public function testSetSameUniqueValueOnDifferentRecordThrowsException() + { + $this->manager->setAttribute(Doctrine::ATTR_VLD, true); + + $r = new ValidatorTest_Person(); + $r->identifier = '1234'; + $r->save(); + + $r = new ValidatorTest_Person(); + $r->identifier = 1234; + try { + $r->save(); + $this->fail("No validator exception thrown on unique validation."); + } catch (Doctrine_Validator_Exception $e) { + $this->pass(); + } + $r->delete(); // clean up + $this->manager->setAttribute(Doctrine::ATTR_VLD, false); } }