From 699a6e1783f4443a3bb6bc129f6cc7130db1b5ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Bundyra?= <michal.bundyra@buddyloans.com>
Date: Wed, 8 Apr 2015 10:49:21 +0100
Subject: [PATCH] prevent duplicate unique index

---
 lib/Doctrine/ORM/Tools/SchemaTool.php         | 10 +++++
 .../Tests/ORM/Tools/SchemaToolTest.php        | 39 +++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php
index fb1ebfcc4..b8e62739b 100644
--- a/lib/Doctrine/ORM/Tools/SchemaTool.php
+++ b/lib/Doctrine/ORM/Tools/SchemaTool.php
@@ -21,6 +21,7 @@ namespace Doctrine\ORM\Tools;
 
 use Doctrine\ORM\ORMException;
 use Doctrine\DBAL\Schema\Comparator;
+use Doctrine\DBAL\Schema\Index;
 use Doctrine\DBAL\Schema\Schema;
 use Doctrine\DBAL\Schema\Table;
 use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector;
@@ -274,6 +275,15 @@ class SchemaTool
 
             if (isset($class->table['uniqueConstraints'])) {
                 foreach ($class->table['uniqueConstraints'] as $indexName => $indexData) {
+                    $uniqIndex = new Index($indexName, $indexData['columns'], true, false, [], isset($indexData['options']) ? $indexData['options'] : []);
+
+                    foreach ($table->getIndexes() as $tableIndexName => $tableIndex) {
+                        if ($tableIndex->isFullfilledBy($uniqIndex)) {
+                            $table->dropIndex($tableIndexName);
+                            break;
+                        }
+                    }
+
                     $table->addUniqueIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, isset($indexData['options']) ? $indexData['options'] : array());
                 }
             }
diff --git a/tests/Doctrine/Tests/ORM/Tools/SchemaToolTest.php b/tests/Doctrine/Tests/ORM/Tools/SchemaToolTest.php
index abae9977f..2bd9916ce 100644
--- a/tests/Doctrine/Tests/ORM/Tools/SchemaToolTest.php
+++ b/tests/Doctrine/Tests/ORM/Tools/SchemaToolTest.php
@@ -116,6 +116,28 @@ class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
 
         $this->assertSame(array(), $customSchemaOptions);
     }
+
+    /**
+     * @group DDC-3671
+     */
+    public function testSchemaHasProperIndexesFromUniqueConstraintAnnotation()
+    {
+        $em = $this->_getTestEntityManager();
+        $schemaTool = new SchemaTool($em);
+
+        $classes = [
+            $em->getClassMetadata(__NAMESPACE__ . '\\UniqueConstraintAnnotationModel'),
+        ];
+
+        $schema = $schemaTool->getSchemaFromMetadata($classes);
+
+        $this->assertTrue($schema->hasTable('unique_constraint_annotation_table'));
+        $table = $schema->getTable('unique_constraint_annotation_table');
+
+        $this->assertEquals(2, count($table->getIndexes()));
+        $this->assertTrue($table->hasIndex('primary'));
+        $this->assertTrue($table->hasIndex('uniq_hash'));
+    }
 }
 
 /**
@@ -148,3 +170,20 @@ class GenerateSchemaEventListener
         $this->schemaCalled = true;
     }
 }
+
+/**
+ * @Entity
+ * @Table(name="unique_constraint_annotation_table", uniqueConstraints={
+ *   @UniqueConstraint(name="uniq_hash", columns={"hash"})
+ * })
+ */
+class UniqueConstraintAnnotationModel
+{
+    /** @Id @Column */
+    private $id;
+
+    /**
+     * @Column(name="hash", type="string", length=8, nullable=false, unique=true)
+     */
+    private $hash;
+}