mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 06:52:09 +01:00
Comparator detects unnecessary change in UNSIGNED field #6065
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @vicdelfant on GitHub (Sep 12, 2018).
Originally assigned to: @morozov on GitHub.
Bug Report
Summary
I have implemented a custom type that requires a
BIGINT UNSIGNEDfor storage in MySQL. In order to achieve this, I overrideType::getSQLDeclaration()in our custom type class as follows:This indeed generates the proper SQL query:
However, after applying this query, subsequent schema diffs keep generating the same
ALTERquery for the same field, with no actual modifications being done.Current behaviour
Running the schema diff keeps generating
ALTERqueries for the field for no apparent reason. At first I thought this was related to #2596, but the comments are left intact. This could also be related to #3021, but I figured the hardcoded "UNSIGNED" string in that issue could actually be part of the cause there.Upon digging further, I found out that
Comparator::diffColumn()is getting false intel:It seems that the
unsignedproperty isn't being set correctly in what's referenced to as$properties2here. This obviously results in a difference while there actually isn't. I then turned toMySqlSchemaManagerbut it seems that it's detecting theunsignedflag properly.How to reproduce
See above - implement a custom type that inherits from the
IntegerTypeand set the$fieldDeclaration['unsigned']property totrue.The schema diff works correctly if the
unsignedflag isn't set (same type, same everything), so it's definitely related to theunsignedproperty.Expected behaviour
Both columns get their
unsignedproperty set totruein theComparator, resulting in an empty$changedPropertiesand thus not resulting in any unnecessaryALTERqueries in the schema diff.@morozov commented on GitHub (Sep 12, 2018):
@vicdelfant thank you for the report. Given that you already have all the needed code in place, could you put together a test case which we could run and reproduce the issue? Otherwise, we'll have to spend time building code from your specification which is not productive. Eventually, this code will turn into a test which covers the fix.
@vicdelfant commented on GitHub (Dec 3, 2018):
Sorry for not getting back about this sooner @morozov!
I have prepared a simple test case: https://github.com/vicdelfant/doctrine-unsigned-type-issue. Since I'm not entirely sure whether it's the ORM or DBAL (or the combination of the two) that's causing issues, I have prepared it as a simple CLI test. Further instructions are in the README.
@vicdelfant commented on GitHub (Dec 8, 2018):
Right. After debugging some more, I think I managed to pinpoint the cause. It's not the DBAL but the ORM that's causing the issue.
The
Comparatorcalled here gets its information from the ORM'sSchemaTool::gatherColumn(), which doesn't include theunsignedproperty simply because it doesn't know that there should be one for the specific entity property we're working with. As a result, internally, there's a difference between the local entity (which hasunsignedset tofalseaccording to the ORM) and the table (which hasunsignedset totrue). Upon schema generation, the custom DBAL type takes over and forcefully adds theunsignedflag, but the difference continues to exist.So it's not the schema comparison that's causing the issue, it's the ORM side of things. If I change the entity's
@ORM\Columnannotation to includeoptions={"unsigned"=true}then everything works as expected. Ideally, however, there'd be a way for the ORM to check with the custom DBAL type so it knows about the unsigned flag, or to have the comparison ignore this change.The above means that this issue actually is a duplicate of #3021.
@vicdelfant commented on GitHub (Dec 8, 2018):
The following could be a fix for both this issue and #3021:
79d6200647. The defaultTypein the DBAL would only need the following placeholder function:The custom type, in turn, could then return:
The above solution has been tested in my PoC repo and it's working. The question is: does this fit with the Doctrine project's vision? It does create a (stronger) dependency between the ORM and DBAL components.
@morozov commented on GitHub (Dec 8, 2018):
Thank you for the info, @vicdelfant. I tried debugging your code briefly, and what I see is when the
$toSchemais built inShemaTool::getUpdateSchemaSql(), theCustomIdType::getSQLDeclaration()method is not invoked (however it probably should). At that moment, the comparator is given wrong structures to compare.I'll transfer this issue to the ORM project.
@beberlei commented on GitHub (Sep 25, 2020):
This can be fixed on your end by doing
@Column(options={'unsigned': true}, ...).