diff --git a/docs/en/reference/annotations-reference.rst b/docs/en/reference/annotations-reference.rst
index 8d40096ca..27271f491 100644
--- a/docs/en/reference/annotations-reference.rst
+++ b/docs/en/reference/annotations-reference.rst
@@ -421,6 +421,13 @@ Required attributes:
- **name**: Name of the Index
- **columns**: Array of columns.
+Optional attributes:
+
+- **options**: Array of platform specific options:
+
+ - ``where``: SQL WHERE condition to be used for partial indexes. It will
+ only have effect on supported platforms.
+
Example:
.. code-block:: php
@@ -1154,6 +1161,13 @@ Required attributes:
- **name**: Name of the Index
- **columns**: Array of columns.
+Optional attributes:
+
+- **options**: Array of platform specific options:
+
+ - ``where``: SQL WHERE condition to be used for partial indexes. It will
+ only have effect on supported platforms.
+
Example:
.. code-block:: php
diff --git a/doctrine-mapping.xsd b/doctrine-mapping.xsd
index fea44a691..a6440a2e8 100644
--- a/doctrine-mapping.xsd
+++ b/doctrine-mapping.xsd
@@ -5,9 +5,9 @@
xmlns:orm="http://doctrine-project.org/schemas/orm/doctrine-mapping"
elementFormDefault="qualified">
-
-
+
@@ -23,27 +23,27 @@
-
+
-
+
-
-
-
-
-
+
+
+
+
+
-
+
@@ -64,7 +64,7 @@
-
+
@@ -73,7 +73,7 @@
-
+
@@ -199,7 +199,7 @@
-
+
@@ -245,7 +245,7 @@
-
+
@@ -253,33 +253,33 @@
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
+
-
-
-
-
+
+
+
+
-
+
@@ -299,13 +299,13 @@
-
+
-
+
@@ -317,16 +317,17 @@
-
+
+
-
+
@@ -334,9 +335,10 @@
-
+
+
@@ -344,7 +346,7 @@
-
+
@@ -352,7 +354,7 @@
-
+
@@ -361,7 +363,7 @@
-
+
@@ -509,7 +511,7 @@
-
+
@@ -528,7 +530,7 @@
-
+
diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
index 3f46e2c95..85f40b2f5 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
@@ -102,11 +102,15 @@ class AnnotationDriver extends AbstractAnnotationDriver
if ($tableAnnot->indexes !== null) {
foreach ($tableAnnot->indexes as $indexAnnot) {
$index = array('columns' => $indexAnnot->columns);
-
+
if ( ! empty($indexAnnot->flags)) {
$index['flags'] = $indexAnnot->flags;
}
+ if ( ! empty($indexAnnot->options)) {
+ $index['options'] = $indexAnnot->options;
+ }
+
if ( ! empty($indexAnnot->name)) {
$primaryTable['indexes'][$indexAnnot->name] = $index;
} else {
@@ -119,6 +123,10 @@ class AnnotationDriver extends AbstractAnnotationDriver
foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) {
$uniqueConstraint = array('columns' => $uniqueConstraintAnnot->columns);
+ if ( ! empty($uniqueConstraintAnnot->options)) {
+ $uniqueConstraint['options'] = $uniqueConstraintAnnot->options;
+ }
+
if ( ! empty($uniqueConstraintAnnot->name)) {
$primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint;
} else {
diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
index e08ee7ae6..45836a6b9 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
@@ -196,11 +196,15 @@ class XmlDriver extends FileDriver
$metadata->table['indexes'] = array();
foreach ($xmlRoot->indexes->index as $indexXml) {
$index = array('columns' => explode(',', (string) $indexXml['columns']));
-
+
if (isset($indexXml['flags'])) {
$index['flags'] = explode(',', (string) $indexXml['flags']);
}
-
+
+ if (isset($indexXml->options)) {
+ $index['options'] = $this->_parseOptions($indexXml->options->children());
+ }
+
if (isset($indexXml['name'])) {
$metadata->table['indexes'][(string) $indexXml['name']] = $index;
} else {
@@ -212,17 +216,18 @@ class XmlDriver extends FileDriver
// Evaluate
if (isset($xmlRoot->{'unique-constraints'})) {
$metadata->table['uniqueConstraints'] = array();
- foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $unique) {
- $columns = explode(',', (string)$unique['columns']);
+ foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $uniqueXml) {
+ $unique = array('columns' => explode(',', (string) $uniqueXml['columns']));
- if (isset($unique['name'])) {
- $metadata->table['uniqueConstraints'][(string)$unique['name']] = array(
- 'columns' => $columns
- );
+
+ if (isset($uniqueXml->options)) {
+ $unique['options'] = $this->_parseOptions($uniqueXml->options->children());
+ }
+
+ if (isset($uniqueXml['name'])) {
+ $metadata->table['uniqueConstraints'][(string)$uniqueXml['name']] = $unique;
} else {
- $metadata->table['uniqueConstraints'][] = array(
- 'columns' => $columns
- );
+ $metadata->table['uniqueConstraints'][] = $unique;
}
}
}
diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
index 2772913cc..c492c0f54 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
@@ -220,27 +220,32 @@ class YamlDriver extends FileDriver
}
}
+ if (isset($indexYml['options'])) {
+ $index['options'] = $indexYml['options'];
+ }
+
$metadata->table['indexes'][$indexYml['name']] = $index;
}
}
// Evaluate uniqueConstraints
if (isset($element['uniqueConstraints'])) {
- foreach ($element['uniqueConstraints'] as $name => $unique) {
- if ( ! isset($unique['name'])) {
- $unique['name'] = $name;
+ foreach ($element['uniqueConstraints'] as $name => $uniqueYml) {
+ if ( ! isset($uniqueYml['name'])) {
+ $uniqueYml['name'] = $name;
}
- if (is_string($unique['columns'])) {
- $columns = explode(',', $unique['columns']);
- $columns = array_map('trim', $columns);
+ if (is_string($uniqueYml['columns'])) {
+ $unique = array('columns' => array_map('trim', explode(',', $uniqueYml['columns'])));
} else {
- $columns = $unique['columns'];
+ $unique = array('columns' => $uniqueYml['columns']);
}
- $metadata->table['uniqueConstraints'][$unique['name']] = array(
- 'columns' => $columns
- );
+ if (isset($uniqueYml['options'])) {
+ $unique['options'] = $uniqueYml['options'];
+ }
+
+ $metadata->table['uniqueConstraints'][$uniqueYml['name']] = $unique;
}
}
diff --git a/lib/Doctrine/ORM/Mapping/Index.php b/lib/Doctrine/ORM/Mapping/Index.php
index ff4532d47..45953a804 100644
--- a/lib/Doctrine/ORM/Mapping/Index.php
+++ b/lib/Doctrine/ORM/Mapping/Index.php
@@ -39,4 +39,9 @@ final class Index implements Annotation
* @var array
*/
public $flags;
+
+ /**
+ * @var array
+ */
+ public $options;
}
diff --git a/lib/Doctrine/ORM/Mapping/UniqueConstraint.php b/lib/Doctrine/ORM/Mapping/UniqueConstraint.php
index 95d99293f..f117d1873 100644
--- a/lib/Doctrine/ORM/Mapping/UniqueConstraint.php
+++ b/lib/Doctrine/ORM/Mapping/UniqueConstraint.php
@@ -34,4 +34,9 @@ final class UniqueConstraint implements Annotation
* @var array
*/
public $columns;
+
+ /**
+ * @var array
+ */
+ public $options;
}
diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php
index 9bca3ed66..db9438c9f 100644
--- a/lib/Doctrine/ORM/Tools/SchemaTool.php
+++ b/lib/Doctrine/ORM/Tools/SchemaTool.php
@@ -267,14 +267,14 @@ class SchemaTool
if( ! isset($indexData['flags'])) {
$indexData['flags'] = array();
}
-
- $table->addIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, (array)$indexData['flags']);
+
+ $table->addIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, (array)$indexData['flags'], isset($indexData['options']) ? $indexData['options'] : array());
}
}
if (isset($class->table['uniqueConstraints'])) {
foreach ($class->table['uniqueConstraints'] as $indexName => $indexData) {
- $table->addUniqueIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName);
+ $table->addUniqueIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, isset($indexData['options']) ? $indexData['options'] : array());
}
}
diff --git a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
index 7a22dc1da..b81b3ba1e 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
+++ b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
@@ -73,14 +73,15 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
return $class;
}
- public function testEntityIndexFlags()
+ public function testEntityIndexFlagsAndPartialIndexes()
{
$class = $this->createClassMetadata('Doctrine\Tests\ORM\Mapping\Comment');
$this->assertEquals(array(
0 => array(
'columns' => array('content'),
- 'flags' => array('fulltext')
+ 'flags' => array('fulltext'),
+ 'options' => array('where' => 'content IS NOT NULL'),
)
), $class->table['indexes']);
}
@@ -95,7 +96,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
'ClassMetadata should have uniqueConstraints key in table property when Unique Constraints are set.');
$this->assertEquals(array(
- "search_idx" => array("columns" => array("name", "user_email"))
+ "search_idx" => array("columns" => array("name", "user_email"), 'options' => array('where' => 'name IS NOT NULL'))
), $class->table['uniqueConstraints']);
return $class;
@@ -938,7 +939,7 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
* @HasLifecycleCallbacks
* @Table(
* name="cms_users",
- * uniqueConstraints={@UniqueConstraint(name="search_idx", columns={"name", "user_email"})},
+ * uniqueConstraints={@UniqueConstraint(name="search_idx", columns={"name", "user_email"}, options={"where": "name IS NOT NULL"})},
* indexes={@Index(name="name_idx", columns={"name"}), @Index(name="0", columns={"user_email"})},
* options={"foo": "bar", "baz": {"key": "val"}}
* )
@@ -1122,7 +1123,7 @@ class User
'orderBy' => NULL,
));
$metadata->table['uniqueConstraints'] = array(
- 'search_idx' => array('columns' => array('name', 'user_email')),
+ 'search_idx' => array('columns' => array('name', 'user_email'), 'options'=> array('where' => 'name IS NOT NULL')),
);
$metadata->table['indexes'] = array(
'name_idx' => array('columns' => array('name')), 0 => array('columns' => array('user_email'))
@@ -1281,7 +1282,7 @@ class Group {}
/**
* @Entity
- * @Table(indexes={@Index(columns={"content"}, flags={"fulltext"})})
+ * @Table(indexes={@Index(columns={"content"}, flags={"fulltext"}, options={"where": "content IS NOT NULL"})})
*/
class Comment
{
@@ -1295,7 +1296,7 @@ class Comment
$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
$metadata->setPrimaryTable(array(
'indexes' => array(
- array('columns' => array('content'), 'flags' => array('fulltext'))
+ array('columns' => array('content'), 'flags' => array('fulltext'), 'options' => array('where' => 'content IS NOT NULL'))
)
));
diff --git a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.ORM.Mapping.Comment.php b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.ORM.Mapping.Comment.php
index 124aafe1d..85cbed4dc 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.ORM.Mapping.Comment.php
+++ b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.ORM.Mapping.Comment.php
@@ -5,7 +5,7 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo;
$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
$metadata->setPrimaryTable(array(
'indexes' => array(
- array('columns' => array('content'), 'flags' => array('fulltext'))
+ array('columns' => array('content'), 'flags' => array('fulltext'), 'options'=> array('where' => 'content IS NOT NULL'))
)
));
diff --git a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.ORM.Mapping.User.php b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.ORM.Mapping.User.php
index 1795793d3..67dbd752d 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.ORM.Mapping.User.php
+++ b/tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests.ORM.Mapping.User.php
@@ -112,11 +112,11 @@ $metadata->mapManyToMany(array(
'orderBy' => NULL,
));
$metadata->table['options'] = array(
- 'foo' => 'bar',
+ 'foo' => 'bar',
'baz' => array('key' => 'val')
);
$metadata->table['uniqueConstraints'] = array(
- 'search_idx' => array('columns' => array('name', 'user_email')),
+ 'search_idx' => array('columns' => array('name', 'user_email'), 'options' => array('where' => 'name IS NOT NULL')),
);
$metadata->table['indexes'] = array(
'name_idx' => array('columns' => array('name')), 0 => array('columns' => array('user_email'))
diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.Comment.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.Comment.dcm.xml
index 659ddccd8..8f02ca852 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.Comment.dcm.xml
+++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.Comment.dcm.xml
@@ -8,7 +8,11 @@
-
+
+
+
+
+
diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.User.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.User.dcm.xml
index 728425a71..28b1e0571 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.User.dcm.xml
+++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.User.dcm.xml
@@ -19,7 +19,11 @@
-
+
+
+
+
+
diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.ORM.Mapping.Comment.dcm.yml b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.ORM.Mapping.Comment.dcm.yml
index 2186f6a27..f37bfdcc6 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.ORM.Mapping.Comment.dcm.yml
+++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.ORM.Mapping.Comment.dcm.yml
@@ -7,3 +7,5 @@ Doctrine\Tests\ORM\Mapping\Comment:
0:
columns: content
flags: fulltext
+ options:
+ where: "content IS NOT NULL"
diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.ORM.Mapping.User.dcm.yml b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.ORM.Mapping.User.dcm.yml
index 6b87472d1..457b24eea 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.ORM.Mapping.User.dcm.yml
+++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/Doctrine.Tests.ORM.Mapping.User.dcm.yml
@@ -69,11 +69,13 @@ Doctrine\Tests\ORM\Mapping\User:
cascade:
- all
lifecycleCallbacks:
- prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
+ prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
postPersist: [ doStuffOnPostPersist ]
uniqueConstraints:
search_idx:
columns: name,user_email
+ options:
+ where: name IS NOT NULL
indexes:
name_idx:
columns: name