Giter Site home page Giter Site logo

Comments (41)

michnovka avatar michnovka commented on July 17, 2024 1

@greg0ire I am using DBAL 4.0.4 which is based on 3.8.6 that includes the linked fix. ORM is at 3.2.1 and there is no newer version. And the issue is ONLY with DBAL 4 not DBAL 3

from migrations.

michnovka avatar michnovka commented on July 17, 2024 1

@greg0ire yes, I get this.

The problem is that when the comparator tries to compare the schemas, it is working with oldSchema and newSchema. oldSchema is Schema instance which is created and populated with data using Doctrine\DBAL\Schema\MySQLSchemaManager and it considers my column to be StringType (cos DB column definition is enum(...) which it doesnt understand, so it says, its StringType - this can be seen in my debug output in comment #1441 (comment)).

This means that when it tries to compare SQL generated between old and new schemas, it calls StringType::getSQLDeclaration output instead of the ActionTypeType::getSQLDeclaration for the old schema.

And this is expected. As if in DB there is no info about which custom type the column is, how can the MySQLSchemaManager assume its ActionTypeType and then gets its SQL from ActionTypeType::getSQLDeclaration to compare with new schema.

Now the new schema is another Schema instance, but this one is created using Doctrine\Migrations\Provider\OrmSchemaProvider and this calls internally EntityManager and that uses PHP code and properly considers the column ActionTypeType. Then new schema's SQL is the proper one, while the old ones is nonsense, as it thinks its a StringType.

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024 1

Ah I get it now, thanks for explaining it again. I think this means the issue is that the DBAL does not understand enum(…), and cannot find a type that will produce the same DDL. I don't see a way around that. I now better get the point of doctrine/dbal#6444, which I now realize was about the same thing.

from migrations.

michnovka avatar michnovka commented on July 17, 2024 1

yes, it all comes to a simple problem - the oldSchema is generated using ONLY DB introspection. And if DB contains no info about which type was used, then it cannot call proper getSQLDeclaration function.

And no, the problem does not simply limit to enum. I can make an example with another custom type which will have the same issue without enums. ALL custom types have this issue in fact, i.e. all custom types with custom getSQLDeclaration which differs from those provided by DBAL package.

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024 1

This looks related: doctrine/dbal#5308 (comment)

from migrations.

michnovka avatar michnovka commented on July 17, 2024 1

Here, Doctrine is reading your database. Does it also read the type as a string here? https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Schema/AbstractSchemaManager.php#L195

No, here it fetches it from DB like this:

   1 => array:10 [
      "TABLE_NAME" => "actions"
      "field" => "type"
      "type" => "enum('submit','cancel')"
      "null" => "NO"
      "key" => ""
      "default" => null
      "EXTRA" => ""
      "comment" => ""
      "characterset" => "utf8mb4"
      "collation" => "utf8mb4_general_ci"
    ]

But this is just one step before _getPortableTableColumnDefinition is called which is where the $this->platform->getDoctrineTypeMapping($dbType); is called, and which we already addressed and debugged in #1441 (comment)

And @greg0ire this is where the issue lies:
https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Schema/MySQLSchemaManager.php#L218

        $column = new Column($tableColumn['field'], Type::getType($type), $options);

specifically the Type::getType($type). Without comments, there is no way at all for the old type to be "guessed" correctly. If I use custom type which has SQL declaration always as int(3), (lets call it CustomInt3Type), then the Column instance will always be deduced as IntegerType and for comparison IntegerType::getSQLDeclaration will be called to be compared against newSchema's CustomInt3Type::getSQLDeclaration. There is just no way for it to know that this int(3) is actually CustomInt3Type and not IntegerType

from migrations.

michnovka avatar michnovka commented on July 17, 2024 1

@berkut1 Thanks for the suggestion, but this is not a solution for my case.

It works in your case when you have 1:1 mapping between DB type INET and your class MY_INET. So your code is 100% certain, when it finds INET type in DB to use that specific type.

But in my case, every ENUM is different. The example I provided is ENUM('submit','cancel') and it uses custom type ActionTypeType extends AbstractEnumType. AbstractEnumClass is my base class for enums, and I have many others. There is e.g. ColorEnumType extends AbstractEnumType which creates ENUM('black','red'). So DB ENUM type maps to multiple PHP Type classes.

from migrations.

michnovka avatar michnovka commented on July 17, 2024

@greg0ire I am tagging you as you authored some of the relevant changes and I know you have deep insight into removing comments in DBAL 4.

I was digging into the code, the issue lies here:

So Doctrine\Migrations\Generator\DiffGenerator::generate() calls createFromSchema to do comparison of old vs new schema. This calls Doctrine\DBAL\Schema\MySQLSchemaManager (which inherits AbstractSchemaManager) and specifically it fails on function _getPortableTableColumnDefinition(). Where the array $tableColumn which this function gets is

 array:11 [
  "table_name" => "actions"
  "field" => "type"
  "type" => "enum('submit','cancel')"
  "null" => "NO"
  "key" => ""
  "default" => null
  "extra" => ""
  "comment" => ""
  "characterset" => "utf8mb4"
  "collation" => "utf8mb4_general_ci"
  "name" => ""
]

This function then calls $type = $this->platform->getDoctrineTypeMapping($dbType) and since enum, or whatever custom type is not recognized, it defaults to StringType.

Now check DBAL 3 code:
https://github.com/doctrine/dbal/blob/893417fee2bc5a94a10a2010ae83cab927e21df3/src/Schema/MySQLSchemaManager.php#L189-L192

This uses the comment to deduce the proper type and override whatever type is in DB. Without this now, DBAL considers any unknown DB type to be StringType and I have no way how to tell it its not a string type. Hence the migration will always consider old schema column to be string.

Now the new schema uses the DiffGenerator::createToSchema() which does not use Doctrine\DBAL\Schema\AbstractSchemaManager but instead Doctrine\Migrations\Provider\OrmSchemaProvider and this uses under the hood EntityManager which of course identifies the column type properly as ActionTypeType or whatever custom type you use.

So, since we removed comments in DBAL 4, how can the fromSchema be generated properly? This uses only DB values, it does not care about type definition in Entity code (thats relevant for toSchema only).

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024

Please upgrade the ORM to 3.8.5: doctrine/dbal#6423

EDIT: I shouldn't answer so hastily

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

@michnovka It seems that when Doctrine reads the schema of your database, the getSQLDeclaration function is not being called, which is why it cannot recognize the type. There might be a bug in https://github.com/doctrine/dbal/blob/4.0.x/src/Platforms/AbstractMySQLPlatform.php

Try debugging this function to determine at which stage the type is being lost:
https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Platforms/AbstractPlatform.php#L2190

Probably, this is a mistaken assumption. Here, two schemas columns are being compared. If initially it was read as StringType, then the error is somewhere earlier.

from migrations.

michnovka avatar michnovka commented on July 17, 2024

@berkut1 this is indeed a mistaken assumption imo, as getSQLDeclaration not being called is a consequence of not having the proper type. The type has to be known in order for that function to be called. And it is called, just for the new schema.

The issue is that oldSchema is created based on database ONLY. It ignores PHP code. And thats good, as the php code defines the new schema, if it took the PHP code as a hint of the type, then migration has no point, as it would be the same type always.

I honestly see no other way than to somehow store in DB the name of the custom type which was used. Which is exactly what the DB comment was used for. WDYT?

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

@michnovka
No, DC2Type comments have been useless since around DBAL 3.x. Doctrine can determine custom types on its own if they are properly registered. You need to find out why, in your case, this is not happening for Enum and where exactly the error is in the code.

from migrations.

michnovka avatar michnovka commented on July 17, 2024

@berkut1 how are they useless when even in 3.9.x there is this code:

https://github.com/doctrine/dbal/blob/893417fee2bc5a94a10a2010ae83cab927e21df3/src/Schema/MySQLSchemaManager.php#L189-L192 ?

And this is where it fails, this is where in 3.8.x version it assigned properly custom type, but in 4.0.x it assigns StringType (as the code assigning type based on comment is missing)

And again, think about what I observed above - the oldSchema is created based on DB data ONLY. not PHP. Only DB. So if DB has no indication about the type, how can it be properly determined for nonstandard types?
newSchema uses PHP code to determine types. And thats good.

Doctrine can determine custom types on its own if they are properly registered.

This has no sense for migrations. If I had customType1 field in table, and I changed it to customType2 field, then did migration, how would doctrine deduce it was before customType1? It is no longer defined and registered. PHP code always reflects only the newSchema.

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

DBAL 3.x should have backward compatibility, that why it can works with DC2Types and without. there was added this https://github.com/doctrine/dbal/blob/893417fee2bc5a94a10a2010ae83cab927e21df3/src/Platforms/AbstractPlatform.php#L108
that people can smoothly migrate from DBAL3 to DBAL4

from migrations.

michnovka avatar michnovka commented on July 17, 2024

With DBAL 3.8.X and doctrine.dbal.disable_type_comments: true the issue is also present.

And of course it is. Read again where and why it happens, I explained exactly where the issue lies. oldSchema is created based on DB details only. If we dont use comments (either as they are removed in DBAL 4, or if we disable them manually in DBAL 3) then oldSchema will have no idea what type was used before.

Thanks for your interest and will to help.

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

Here,
https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Schema/MySQLSchemaManager.php#L135
and
https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Schema/MySQLSchemaManager.php#L218
Doctrine is trying to map your registered custom types to your database. What happens when it tries to map the Enum type in your case?

UPD:
You also can check if your type registered, here:
image

from migrations.

michnovka avatar michnovka commented on July 17, 2024

https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Schema/MySQLSchemaManager.php#L135

dump($type, $dbType);

gives

1 "string"
2 "enum"

and

https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Schema/MySQLSchemaManager.php#L218

dump($column);

gives

Doctrine\DBAL\Schema\Column {#926
  #_name: "type"
  #_namespace: null
  #_quoted: false
  #_type: Doctrine\DBAL\Types\StringType {#636}
  #_length: 0
  #_precision: null
  #_scale: 0
  #_unsigned: false
  #_fixed: false
  #_notnull: true
  #_default: null
  #_autoincrement: false
  #_platformOptions: []
  #_columnDefinition: null
  #_comment: ""
}

UPD:
I checked and the typeRegistry does contain my custom type ActionTypeType

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024

@michnovka it's unclear to me whether you know what platform-aware comparison is. In case you don't, since DBAL 3.2.0, platform-aware comparison allows to compare the generated SQL instead of comparing schemas. This means that 2 different schemas could result in an empty diff, if they result in the same SQL being generated. More on this here: https://www.doctrine-project.org/2021/11/26/dbal-3.2.0.html

Sorry if you already know this, it's genuinely hard to tell for me.

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

Here, Doctrine is reading your database. Does it also read the type as a string here?
https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Schema/AbstractSchemaManager.php#L195

leads to https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Schema/MySQLSchemaManager.php#L344

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

Ah, I understand now. It calls Type::getType with enum and cannot find such a type because it doesn't exist.
In Symfony, you can work around this by registering another type to let Doctrine know about it: https://symfony.com/doc/current/doctrine/dbal.html#registering-custom-mapping-types-in-the-schematool (this instruction correct for DBAL3)
In your case, for DBAL 4 with Symfony, you need to do it like this:

        mapping_types:
            enum: ancestor_enum 
        types:
            ancestor_enum : 'App\Model\AncestorEnumType' 

Unfortunately, I can't help with how to do this without Symfony.

UPD:
In the example, I specified the type as ancestor, assuming that you can register it in the mapping (mapping_types) only once. For all your other Enums, it will be enough to inherit from it and register only as a custom type (types). Otherwise, you would have to duplicate entries for all Enums in mapping_types.

from migrations.

michnovka avatar michnovka commented on July 17, 2024

@greg0ire as a temporary workaround, how can I tell migration to ignore certain columns? Thanks!

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024

Maybe you can use asset filtering, but I don't think it works at the column level.

from migrations.

michnovka avatar michnovka commented on July 17, 2024

So the issue is this:

  1. we get table columns in raw format from DB using DBAL\Schema\AbstractSchemaManager::fetchTableColumnsByTable() This is an array like
   1 => array:10 [
      "TABLE_NAME" => "actions"
      "field" => "type"
      "type" => "enum('submit','cancel')"
      "null" => "NO"
      "key" => ""
      "default" => null
      "EXTRA" => ""
      "comment" => ""
      "characterset" => "utf8mb4"
      "collation" => "utf8mb4_general_ci"
    ]
  1. This is converted to DBAL\Schema\Column instance, which has incorrect type (as DBAL has no idea what custom type is to be used without comments, so it guesses best match from default types)
  2. then Column::getType()::getSQLDeclaration() is called to obtain incorrect SQL

And on the new schema, we get correct type for column and call its getSQLDeclaration()

These do not match.


Proposed solution:

Why not leverage Column::$_columnDefinition for the old schema? Lets populate this field inside AbstractSchemaManager::_getPortableTableColumnDefinition.

I dont understand why AbstractPlatform::columnsEqual() unsets this. But if we dont unset it and specify it explicitly for old schema, the comparison would be done properly

@greg0ire WDYT?

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024

Sounds good, feel free to give it a try, and see if anything breaks 👍

from migrations.

michnovka avatar michnovka commented on July 17, 2024

I tried to go this way and I am afraid this would create tons of unexpected issues. There are specific test cases that ensure that

Schema diff is empty, since only columnDefinition changed from null (not detected) to a defined one

AbstractComparatorTestCase::testWillNotProduceSchemaDiffOnTableWithAddedCustomSchemaDefinition

so for whatever reason this is considered important. Even the comment in the AbstractPlatform::columsEqual talks about this specifically to ignore the column definition.

So maybe a solution would be to add comments back so that the type can be deduced properly?

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024

I don't think that's the direction we want to go, no. Re-reading the cookbook you mentioned I see

In this case however Schema-Tool update will have a hard time not to request changes for this column on each call.

It seems like that might have been fixed in doctrine/dbal#5224, which might make solution 1 the way to go here.

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

@michnovka
I don't know why you ignored my solution #1441 (comment). For reference, I had a very similar problem, not with enum, but with the inet type, which is unknown to Doctrine. It tried, as in your case, to convert it to VARCHAR in the down() method and constantly generated diff migrations.

As I mentioned in my comment on the instructions, I solved the problem for myself in this way:

doctrine:
    dbal:
        mapping_types:
            inet: my_inet

        types:
            my_inet: { class: 'App\Model\InetType' }

I want to clarify, as stated in the instructions at https://www.doctrine-project.org/projects/doctrine-orm/en/3.2/cookbook/mysql-enums.html, it is recommended to do it like this

$conn->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');

but this solution works only for DBAL3. For DBAL4, you need to refer not to string but to your newly registered custom type, as I indicated in my previous comment.

However, if you haven't tried this solution at all, you can first refer to string; it might work with enum.

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

@michnovka

Yes, I understand, which is why I initially suggested creating an abstract Enum class and registering it, then inheriting from it for custom types.
If I understand correctly how Doctrine works with types, when comparing schemas, it only compares the types of SQL, and the comparison of ColumnDeclarationSQL happens only at the final stage: https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Platforms/AbstractPlatform.php#L2199-L2204

In other words, you need to make Doctrine understand that it has a base Enum class for comparison, with which it will compare all the descendants of this class.
This test for DBAL3 with disabled type comments, show the logic:
https://github.com/doctrine/dbal/blob/893417fee2bc5a94a10a2010ae83cab927e21df3/tests/Platforms/AbstractPlatformTestCase.php#L1448

from migrations.

michnovka avatar michnovka commented on July 17, 2024

@berkut1 this does not work for the reason I mentioned. The same way that for doctrine VARCHAR(16) and VARCHAR(65) are both the same StringType, it considers ENUM('black','red') and ENUM('fast','slow') as the same type. Since the type has no idea about which enum to use as a base.

So what I can do, is map ENUM(WHATEVER) to some "abstract" Enum class (notice the quotes around abstract, as the class cannot be abstract, as it has to be instantiated).

But then, how can this "abstract" enum class generate valid SQL code in getSQLDeclaration, and how can it cast properly to the actual specific PHP enum in convertToPHPValue ? So the approach I took, is I do actually have an AbstractEnumType class and I extend this for every single PHP enum I want to use as MySQL ENUM. This way every column that is mapped to this type is actually an instance of some child of AbstractEnumType but it is a different child for every enum I use, therefore it performs proper casting and can create the appropriate SQL declaration.

And this is where we come to the issue which I am not sure how to address with some easy fix. ENUM('black','red') and ENUM('fast','slow') should be treated as different types.

The only solution is to compare the SQL read from INFORMATION_SCHEMA with the SQL generated for a new schema.

Now we do:

  1. read INFORMATION_SCHEMA from DB and populate old schema's Column using DBAL's SchemaManager<- this is where it fails, as the Type field of old schema is not 100% correct with custom types
  2. populate new schema's Column using Migration's DiffGenerator::createToSchema <- this is correct, as it reads types properly from attributes
  3. We compare the 2 columns <- they always differ as the old schema cannot know the proper type to use.

I tried to implement #1441 (comment) leveraging Column::$_columnDefinition but this is not OK, it creates tons of failing tests because this is not what the field was meant for.

from migrations.

michnovka avatar michnovka commented on July 17, 2024

@greg0ire Idea for workaround:

How about we implement an attribute #[Doctrine\Migration\Mapping\IgnoreInMigrations] and if we use it on a type, it will ignore the column, or potentially whole Entity? If new schema has a column/entity with this attribute, it will simply not care if the old schema has it/does not have it/has it different. Simply skip any check.

This is different than DBAL's schema_filter, since that one filters out tables that are present in the database.

Migration bundle can then show a warning that some columns/tables were ignored. And its up to the developer to manage such fields in migrations manually.

from migrations.

PowerKiKi avatar PowerKiKi commented on July 17, 2024

I am having the exact same issue as @michnovka. I have a bunch of different PHP enums, each of them is used to declare a DBAL type enum via inheritance of a custom PhpEnumType DBAL type. That parent will use ENUM type in DB, instead of the VARCHAR used by the column attribute enumType. So it's basically https://knplabs.com/en/blog/how-to-map-a-php-enum-with-doctrine-in-a-symfony-project/

But now migrations are always re-generated for those columns :-/

@michnovka, the workaround you suggest seems like quite a big regression feature-wise. Having auto-managed enums is really great. And there is no reason that Doctrine should not treat ENUM differently than any other types. It should be supported as well as other types. And if not out-of-the-box, at least Doctrine should let us the possibility to implement them with reasonable effort.

@greg0ire I get it that DBAL does not require comments anymore for its out of the box behavior. Doctrine is improving, that's good for all of us. But it does not mean that comments don't have any real use outside of DBAL internals, to solve real use-cases.

The fact that the removal of comment broke the cookbook to use ENUM in DB is very telling. You suggest to fallback on the cookbook that use VARCHAR instead. It might work for some, but it might also be unacceptable for some project to change all column type from ENUM to VARCHAR.

I think this whole thing boils down to: how can Doctrine supports ENUM as a first-class citizen, and not what seems to only be an afterthought ?

PS: but doctrine/dbal#5308 (comment) suggests that there is a broader issue that goes beyond ENUM too...

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024

to change all column type from ENUM to VARCHAR.

Can you clarify exactly what you mean by that?

how can Doctrine supports ENUM as a first-class citizen, and not what seems to only be an afterthought ?

It would seem like it cannot

from migrations.

PowerKiKi avatar PowerKiKi commented on July 17, 2024

to change all column type from ENUM to VARCHAR.

Can you clarify exactly what you mean by that?

What I mean that is that before DBAL 4.0, the cookbook solution 2 allowed to have a DB type of ENUM.

But now it will re-generate migrations everytime. So it appears the only way to avoid that, is to use the built-in support for PHP enum, via either the enumType attribute, or the implicit typed field mapper, as shown below. Because I don't think the cookbook solution 1 can work with PHP enum without unreasonable boilerplate. But both of those solutions will change the DB colum from ENUM to VARCHAR, and thus losing the advantages of DB enum. And our DB will become a mess of non-validated data.

Given this entity:

#[ORM\Entity]
class Task
{
    #[ORM\Column(type: 'Priority')]
    private Priority $priorityViaCustomType;

    #[ORM\Column(enumType: Priority::class)]
    private Priority $priorityViaEnumType;

    #[ORM\Column]
    private Priority $priorityViaTypedFieldMapper;
}

I will get the following SQL for MariaDB:

ALTER TABLE task
ADD priority_via_custom_type ENUM('low', 'normal', 'high') NOT NULL COMMENT '(DC2Type:Priority)', -- DBAL 4.0 won't have the comment anymore, so it will generate migrations everytime 😭 
ADD priority_via_enum_type VARCHAR(255) NOT NULL, -- Not validated by DB 😭
ADD priority_via_typed_field_mapper VARCHAR(255) NOT NULL; -- Not validated by DB 😭

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

@PowerKiKi If your database has dependencies on the ENUM attribute type, which affect data consistency, doesn't that indicate you have database architecture issues?
I think you won't be able to convince Doctrine contributors to change their opinion about ENUM unless you take on the monumental task of implementing ENUM support for all the database systems Doctrine works with.

from migrations.

PowerKiKi avatar PowerKiKi commented on July 17, 2024

You are correct, Doctrine won't change their opinion, and that's fine by me. However they could make it possible to implement it with custom code, and they should definitely strive not to break use-cases, as long as the maintenance cost is reasonable.

At best, dropping comments generated a lot of confusion, or at worse it broke some use-cases as illustrated by the amount of activity around that topic:

And it is not only limited to enum, according to doctrine/dbal#5308 (comment)

It is a bit frustrating because there have been people warning of the situation very early.

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

You mentioned my issue as well :)
Actually, I welcome the new type definition system because it solved (at least for me) many non-obvious errors that DC2Type was hiding by disabling part of the code. I have more of a question about the remnants of DC2Type, such as inet -> string, causing DBAL3 to ignore the schema and assume that INET = VARCHAR and left INET in migrations. However, in DBAL4 the logic changed, but the inet -> string rule remained, which seems strange and will be a surprise for many when they find out that all INETs have become VARCHARs. It would be more appropriate to remove inet -> string (and other similar types) altogether so that an exception is thrown and people can create a custom type themselves.

However, I don't understand why you can't do something similar for ENUM. I don't see a reason why it shouldn't work, unless if you're using third-party packages.

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024

But both of those solutions will change the DB colum from ENUM to VARCHAR

🤔

Then why does the cook book solution 1 mention enums? columnDefinition: "ENUM('visible', 'invisible')"

from migrations.

PowerKiKi avatar PowerKiKi commented on July 17, 2024

columnDefinition: "ENUM('visible', 'invisible')" will "not work", meaning that it will keep generating migrations. Below I force to update the DB structure, then immediately ask for a diff. This should always be empty, but it incorrectly think that my field is not the same:

#[ORM\Column(type: "string", columnDefinition: "ENUM('visible', 'invisible')")]
private $myTestField;
$ ./bin/doctrine orm:schema-tool:update --force && ./bin/doctrine orm:schema-tool:update --dump-sql | grep task
 Updating database schema...

     11 queries were executed

                                                                                                                        
 [OK] Database schema updated successfully!                                                                             
                                                                                                                        

ALTER TABLE task CHANGE my_test_field my_test_field ENUM('visible', 'invisible');    <=== INCORRECT

So that solution has no advantage over solution 2, because both generate infinite migrations. And it is very difficult to scale, and possibly requires a lost of copy/paste, since PHP attributes cannot use expressions.

So if we are stuck with infinite migrations anyway, I might as well use solution 2, which is easy to use and scale much better.

So the only choices we have are:

  • VARCHAR with non-validated DB data
  • ENUM with infinite migrations

It's a rather annoying regression in both cases in my opinion

from migrations.

greg0ire avatar greg0ire commented on July 17, 2024

columnDefinition: "ENUM('visible', 'invisible')" will "not work", meaning that it will keep generating migrations.

Weird, because I stumbled upon doctrine/dbal#5224 recently, which is supposed to prevent that.

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

Weird, because I stumbled upon doctrine/dbal#5224 recently, which is supposed to prevent that.

I suspect it's the same problem I tried to describe here using INET as an example. Apparently, I'm not very good at explaining things :)

from migrations.

berkut1 avatar berkut1 commented on July 17, 2024

@PowerKiKi @michnovka
If you are using ORM, could you test a theory? Remove this check (or only 464 line) and see if it helps with ENUM.
https://github.com/doctrine/orm/blob/9b09cd03c0f4577174dbf7af92644fa8f78faf64/src/Tools/SchemaTool.php#L463-L465

Especially if you are using this solution - https://www.doctrine-project.org/projects/doctrine-orm/en/3.2/cookbook/mysql-enums.html#solution-1-mapping-to-varchars

from migrations.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.