Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fields for unique constraints #8629

Merged
merged 11 commits into from
Apr 18, 2021
32 changes: 30 additions & 2 deletions docs/en/reference/annotations-reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,8 @@ Required attributes:


- **name**: Name of the Index
- **columns**: Array of columns.
- **fields**: Array of fields. Exactly one of **fields**, **columns** is required.
- **columns**: Array of columns. Exactly one of **fields**, **columns** is required.

Optional attributes:

Expand All @@ -535,6 +536,19 @@ Basic example:
{
}

Basic example using fields:

.. code-block:: php

<?php
/**
* @Entity
* @Table(name="ecommerce_products",indexes={@Index(name="search_idx", fields={"name", "email"})})
*/
class ECommerceProduct
{
}

Example with partial indexes:

.. code-block:: php
Expand Down Expand Up @@ -1272,7 +1286,8 @@ Required attributes:


- **name**: Name of the Index
- **columns**: Array of columns.
- **fields**: Array of fields. Exactly one of **fields**, **columns** is required.
- **columns**: Array of columns. Exactly one of **fields**, **columns** is required.

Optional attributes:

Expand All @@ -1294,6 +1309,19 @@ Basic example:
{
}

Basic example using fields:

.. code-block:: php

<?php
/**
* @Entity
* @Table(name="ecommerce_products",uniqueConstraints={@UniqueConstraint(name="search_idx", fields={"name", "email"})})
*/
class ECommerceProduct
{
}

Example with partial indexes:

.. code-block:: php
Expand Down
4 changes: 3 additions & 1 deletion doctrine-mapping.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,8 @@
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="optional"/>
<xs:attribute name="columns" type="xs:string" use="required"/>
<xs:attribute name="columns" type="xs:string" use="optional"/>
<xs:attribute name="fields" type="xs:string" use="optional"/>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>

Expand All @@ -351,6 +352,7 @@
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="optional"/>
<xs:attribute name="columns" type="xs:string" use="required"/>
<xs:attribute name="fields" type="xs:string" use="optional"/>
<xs:attribute name="flags" type="xs:string" use="optional"/>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
Expand Down
47 changes: 45 additions & 2 deletions lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

use function class_exists;
use function constant;
use function count;
use function defined;
use function get_class;
use function is_array;
Expand Down Expand Up @@ -110,7 +111,28 @@ public function loadMetadataForClass($className, ClassMetadata $metadata)

if ($tableAnnot->indexes !== null) {
foreach ($tableAnnot->indexes as $indexAnnot) {
$index = ['columns' => $indexAnnot->columns];
$index = [];

if (! empty($indexAnnot->columns)) {
$index['columns'] = $indexAnnot->columns;
}

if (! empty($indexAnnot->fields)) {
$index['fields'] = $indexAnnot->fields;
}

if (
isset($index['columns'], $index['fields'])
|| (
! isset($index['columns'])
&& ! isset($index['fields'])
)
) {
throw MappingException::invalidIndexConfiguration(
$className,
(string) ($indexAnnot->name ?? count($primaryTable['indexes']))
);
}

if (! empty($indexAnnot->flags)) {
$index['flags'] = $indexAnnot->flags;
Expand All @@ -130,7 +152,28 @@ public function loadMetadataForClass($className, ClassMetadata $metadata)

if ($tableAnnot->uniqueConstraints !== null) {
foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) {
$uniqueConstraint = ['columns' => $uniqueConstraintAnnot->columns];
$uniqueConstraint = [];

if (! empty($uniqueConstraintAnnot->columns)) {
$uniqueConstraint['columns'] = $uniqueConstraintAnnot->columns;
}

if (! empty($uniqueConstraintAnnot->fields)) {
$uniqueConstraint['fields'] = $uniqueConstraintAnnot->fields;
}

if (
isset($uniqueConstraint['columns'], $uniqueConstraint['fields'])
|| (
! isset($uniqueConstraint['columns'])
&& ! isset($uniqueConstraint['fields'])
)
) {
throw MappingException::invalidUniqueConstraintConfiguration(
$className,
(string) ($uniqueConstraintAnnot->name ?? count($primaryTable['uniqueConstraints']))
);
}

if (! empty($uniqueConstraintAnnot->options)) {
$uniqueConstraint['options'] = $uniqueConstraintAnnot->options;
Expand Down
47 changes: 45 additions & 2 deletions lib/Doctrine/ORM/Mapping/Driver/AttributeDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use function assert;
use function class_exists;
use function constant;
use function count;
use function defined;

class AttributeDriver extends AnnotationDriver
Expand Down Expand Up @@ -76,7 +77,28 @@ public function loadMetadataForClass($className, ClassMetadata $metadata): void

if (isset($classAttributes[Mapping\Index::class])) {
foreach ($classAttributes[Mapping\Index::class] as $indexAnnot) {
$index = ['columns' => $indexAnnot->columns];
$index = [];

if (! empty($indexAnnot->columns)) {
$index['columns'] = $indexAnnot->columns;
}

if (! empty($indexAnnot->fields)) {
$index['fields'] = $indexAnnot->fields;
}

if (
isset($index['columns'], $index['fields'])
|| (
! isset($index['columns'])
&& ! isset($index['fields'])
)
) {
throw MappingException::invalidIndexConfiguration(
$className,
(string) ($indexAnnot->name ?? count($primaryTable['indexes']))
);
}

if (! empty($indexAnnot->flags)) {
$index['flags'] = $indexAnnot->flags;
Expand All @@ -96,7 +118,28 @@ public function loadMetadataForClass($className, ClassMetadata $metadata): void

if (isset($classAttributes[Mapping\UniqueConstraint::class])) {
foreach ($classAttributes[Mapping\UniqueConstraint::class] as $uniqueConstraintAnnot) {
$uniqueConstraint = ['columns' => $uniqueConstraintAnnot->columns];
$uniqueConstraint = [];

if (! empty($uniqueConstraintAnnot->columns)) {
$uniqueConstraint['columns'] = $uniqueConstraintAnnot->columns;
}

if (! empty($uniqueConstraintAnnot->fields)) {
$uniqueConstraint['fields'] = $uniqueConstraintAnnot->fields;
}

if (
isset($uniqueConstraint['columns'], $uniqueConstraint['fields'])
|| (
! isset($uniqueConstraint['columns'])
&& ! isset($uniqueConstraint['fields'])
)
) {
throw MappingException::invalidUniqueConstraintConfiguration(
$className,
(string) ($uniqueConstraintAnnot->name ?? count($primaryTable['uniqueConstraints']))
);
}

if (! empty($uniqueConstraintAnnot->options)) {
$uniqueConstraint['options'] = $uniqueConstraintAnnot->options;
Expand Down
47 changes: 45 additions & 2 deletions lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

use function assert;
use function constant;
use function count;
use function defined;
use function explode;
use function file_get_contents;
Expand Down Expand Up @@ -212,7 +213,28 @@ public function loadMetadataForClass($className, ClassMetadata $metadata)
if (isset($xmlRoot->indexes)) {
$metadata->table['indexes'] = [];
foreach ($xmlRoot->indexes->index as $indexXml) {
$index = ['columns' => explode(',', (string) $indexXml['columns'])];
$index = [];

if (isset($indexXml['columns']) && ! empty($indexXml['columns'])) {
$index['columns'] = explode(',', (string) $indexXml['columns']);
}

if (isset($indexXml['fields'])) {
$index['fields'] = explode(',', (string) $indexXml['fields']);
}

if (
isset($index['columns'], $index['fields'])
|| (
! isset($index['columns'])
&& ! isset($index['fields'])
)
) {
throw MappingException::invalidIndexConfiguration(
$className,
(string) ($indexXml['name'] ?? count($metadata->table['indexes']))
);
}

if (isset($indexXml['flags'])) {
$index['flags'] = explode(',', (string) $indexXml['flags']);
Expand All @@ -234,7 +256,28 @@ public function loadMetadataForClass($className, ClassMetadata $metadata)
if (isset($xmlRoot->{'unique-constraints'})) {
$metadata->table['uniqueConstraints'] = [];
foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $uniqueXml) {
$unique = ['columns' => explode(',', (string) $uniqueXml['columns'])];
$unique = [];

if (isset($uniqueXml['columns']) && ! empty($uniqueXml['columns'])) {
$unique['columns'] = explode(',', (string) $uniqueXml['columns']);
}

if (isset($uniqueXml['fields'])) {
$unique['fields'] = explode(',', (string) $uniqueXml['fields']);
}

if (
isset($unique['columns'], $unique['fields'])
|| (
! isset($unique['columns'])
&& ! isset($unique['fields'])
)
) {
throw MappingException::invalidUniqueConstraintConfiguration(
$className,
(string) ($uniqueXml['name'] ?? count($metadata->table['uniqueConstraints']))
);
}

if (isset($uniqueXml->options)) {
$unique['options'] = $this->parseOptions($uniqueXml->options->children());
Expand Down
66 changes: 58 additions & 8 deletions lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,35 @@ public function loadMetadataForClass($className, ClassMetadata $metadata)
$indexYml['name'] = $name;
}

if (is_string($indexYml['columns'])) {
$index = ['columns' => array_map('trim', explode(',', $indexYml['columns']))];
} else {
$index = ['columns' => $indexYml['columns']];
$index = [];

if (isset($indexYml['columns'])) {
if (is_string($indexYml['columns'])) {
$index['columns'] = array_map('trim', explode(',', $indexYml['columns']));
} else {
$index['columns'] = $indexYml['columns'];
}
}

if (isset($indexYml['fields'])) {
if (is_string($indexYml['fields'])) {
$index['fields'] = array_map('trim', explode(',', $indexYml['fields']));
} else {
$index['fields'] = $indexYml['fields'];
}
}

if (
isset($index['columns'], $index['fields'])
|| (
! isset($index['columns'])
&& ! isset($index['fields'])
)
) {
throw MappingException::invalidIndexConfiguration(
$className,
$indexYml['name']
);
}

if (isset($indexYml['flags'])) {
Expand All @@ -257,10 +282,35 @@ public function loadMetadataForClass($className, ClassMetadata $metadata)
$uniqueYml['name'] = $name;
}

if (is_string($uniqueYml['columns'])) {
$unique = ['columns' => array_map('trim', explode(',', $uniqueYml['columns']))];
} else {
$unique = ['columns' => $uniqueYml['columns']];
$unique = [];

if (isset($uniqueYml['columns'])) {
if (is_string($uniqueYml['columns'])) {
$unique['columns'] = array_map('trim', explode(',', $uniqueYml['columns']));
} else {
$unique['columns'] = $uniqueYml['columns'];
}
}

if (isset($uniqueYml['fields'])) {
if (is_string($uniqueYml['fields'])) {
$unique['fields'] = array_map('trim', explode(',', $uniqueYml['fields']));
} else {
$unique['fields'] = $uniqueYml['fields'];
}
}

if (
isset($unique['columns'], $unique['fields'])
|| (
! isset($unique['columns'])
&& ! isset($unique['fields'])
)
) {
throw MappingException::invalidUniqueConstraintConfiguration(
$className,
$uniqueYml['name']
);
}

if (isset($uniqueYml['options'])) {
Expand Down
8 changes: 7 additions & 1 deletion lib/Doctrine/ORM/Mapping/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ final class Index implements Annotation
/** @var array<string> */
public $columns;

/** @var array<string> */
public $fields;

/** @var array<string> */
public $flags;

Expand All @@ -45,16 +48,19 @@ final class Index implements Annotation

/**
* @param array<string> $columns
* @param array<string> $fields
* @param array<string> $flags
* @param array<string> $options
*/
public function __construct(
array $columns,
?array $columns = null,
?array $fields = null,
?string $name = null,
?array $flags = null,
?array $options = null
) {
$this->columns = $columns;
$this->fields = $fields;
$this->name = $name;
$this->flags = $flags;
$this->options = $options;
Expand Down
Loading