doctrine / dbal

Doctrine Database Abstraction Layer
https://www.doctrine-project.org/projects/dbal.html
MIT License
9.43k stars 1.33k forks source link

PostgreSQL domain and custom types schema diff #3215

Open JindrichPilar opened 6 years ago

JindrichPilar commented 6 years ago
Q A
BC Break Don't know, didn't try on different version
Version 2.7.1

Summary

I am trying to use PostgreSQL (9.3+) domains with Doctrine custom types.

The problem is Doctrine diff tool loads the type "under" the domain, which doesn't match the column definition in Entity (which uses the domain name) and generates (over and over) wrong migrations.

I suspect this behavior is related to https://github.com/doctrine/dbal/issues/1383

How to reproduce

Full example at the end of the issue.

Expected behavior

When a custom type with same name as a domain exists, differ should generate SQL with the domain name, not the type "under" the domain.

Full example

Full example: For example email:

create domain email as varchar(60)  constraint email_check check (length((VALUE)) >= 1)
<?php

declare(strict_types=1);

namespace App\Doctrine\Type;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;

class EmailType
  extends
  Type
{

  public const NAME = 'email';

  /**
   * @override
   */
  public function convertToDatabaseValue(
    $value,
    AbstractPlatform $platform
  ) {
    // To prevent casting [] == 0 == '' == false
    if ($value === null) {
      return null;
    }

    if (!\is_string($value)) {
      throw ConversionException::conversionFailedInvalidType($value, self::NAME, []);
    }

    return $value;
  }

  /**
   * @override
   */
  public function convertToPHPValue(
    $value,
    AbstractPlatform $platform
  ) {
    return $value;
  }

  /**
   * @override
   */
  public function getName()
  {
    return self::NAME;
  }

  /**
   * @override
   */
  public function getSQLDeclaration(
    array $fieldDeclaration,
    AbstractPlatform $platform
  ) {
    return 'public.'.self::NAME;
  }

  public function requiresSQLCommentHint(AbstractPlatform $platform)
  {
    return true;
  }
}
<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="person")
 * @ORM\Entity
 */
class Person
{
  /**
   * @var string
   *
   * @ORM\Column(
   *   name="email",
   *   type="email",
   *   nullable=false
   * )
   */
  private $email;
}
JakubKontra commented 6 years ago

Same problem. @Majkl578 can you help please?