-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Type Mapping Discrepancies Between DBAL3 and DBAL4 #6466
Comments
The same problem exists with the dbal/src/Platforms/PostgreSQLPlatform.php Line 720 in 9042447
While we can override dbal/src/Schema/PostgreSQLSchemaManager.php Line 412 in 9042447
It is subsequently defined as dbal/src/Schema/PostgreSQLSchemaManager.php Line 275 in 9042447
Then, as dbal/src/Platforms/AbstractPlatform.php Lines 1869 to 1872 in 9042447
However, But then, why are these cases: dbal/src/Schema/PostgreSQLSchemaManager.php Line 318 in 9042447
and also initializeDoctrineTypeMappings() here if they will never work?
UPD: Sorry, actually it is possible to override, but you need to override doctrine:
dbal:
mapping_types:
float4: base_real
types:
base_real: { class: 'App\Entity\BaseRealType' }
wide_type: { class: 'App\Entity\WideType' } #inherit from class base_real
depth_type: { class: 'App\Entity\DepthType' } #inherit from class base_real However, in that case, the existence of |
You've expressed in doctrine/migrations#1441 (comment) that you maybe did not explained things very well, and I after reading this issue several times, I'm indeed super confused. Let me try to list the things that confuse me here, hopefully we can get something out of it.
OK? What is the strange behavior?
What do you mean by "recognize"?
What's a migration type?
Where/how does it do that?
Hang on. Didn't you just said Doctrine decide the type was VARCHAR?! Super confusing
What did "this trick" achieve, and how can you tell it no longer works? Then you quote this:
What is the DBAL equivalent of this DoctrineBundle definition? What does
What is |
A few years ago, if Doctrine didn't support a certain type but you wanted it to, and also wanted Doctrine migrations to work with your desired type, you would add an entry like this: doctrine:
dbal:
mapping_types:
cidr: string ( dbal/src/Platforms/PostgreSQLPlatform.php Line 706 in 9042447
And in DBAL3 it actually worked. You would add an entry like unknown_type: string , and Doctrine would handle this type as a string while not changing the SQL migration, avoiding attempts to convert the unknown type to VARCHAR . So, if we used the SQL attribute type CIDR , Doctrine would not change it to VARCHAR (if your DB schema already with CIDR).
If Doctrine doesn't support a type, it throws the following error:
This can be resolved if you add an entry like this doctrine:
dbal:
mapping_types:
new_type: string or create a PR like this #6463
Sorry, I meant SQL attribute types in table, for example, the SQL
I didn't try to find the cause and compare DBAL3 and DBAL4 to see where the difference happens, because I was trying to ask if this behavior is normal for DBAL4.
I don't know how else to explain it since I already gave an example. Alright, I'll try again :) In ORM with DBAL3, an entry like this: #[ORM\Column(name: "ip_inet", type: Types::STRING, nullable: false)]
private string $ipInet; won't try to generate a new migration. So, if our DB schema looks like this: CREATE TABLE tbl (
ip_inet INET NOT NULL
); It will stay unchanged. But in DBAL4, it will generate a migration and change
it is equivalent to: App\Entity\InetType it's just a custom type with: public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
return 'INET';
}
This is a property from the SQL query for PostgreSQL, based on which Doctrine determines which data types are used in table attributes. dbal/src/Schema/PostgreSQLSchemaManager.php Line 424 in 9042447
But that's not important and is unrelated to the main question in this issue. I mentioned it earlier because some lines of code confused me. |
Ok… this is quite long and goes in many directions, but I think if I had to sum it up, I would say the following: Now that platform-aware comparison is the only way to go, is there a point in having a type mapping that maps e.g. the Is that what this issue is about? If yes, personally, I think it might be just a remnant of legacy DBAL versions. If I remove that line and run the tests, they do not fail. I'd be interested to know what other maintainers think about this. @morozov @derrabus , maybe you know more about this? Now, regarding the issue about the wrong diff, it feels like the part that is not taken into account is the |
No, no, you misunderstood :) The solution of creating a custom type ( The problem is that previously with DBAL3, we could simply tell Doctrine that an unknown type is a string (as it exists with I brought up this topic in the ENUM discussion because there's a similar approach where we define an entity property as enum but use string type. In DBAL3, this worked fine, but in DBAL4, it now changes to
I can debug later to pinpoint where exactly the differences occur. |
No idea. |
OK :( 2 things:
Let's focus on 2. for now, and if we find a solution, then we might consider deprecating and removing the supposedly useless mappings. |
Very interesting, it turns out the reason is related to my previous issue doctrine/orm#11502. Previously, due to a bug, DBAL3 didn't distinguish between dbal/src/Platforms/AbstractPlatform.php Lines 2199 to 2204 in 9042447
To explain in more detail: This entry, says that the data type is expected to be #[ORM\Column(name: "attr_inet", type: Types::STRING, nullable: false)]
private string $attr_inet; In DBAL3, such "masking" would allow the So, it turns out the problem is in ORM, and indirectly in DBAL4 (because here was fixed an old bug)? :) |
Hang on, so it's not using the SQL declaration of your INET type? dbal/src/Platforms/AbstractPlatform.php Line 1372 in 9042447
EDIT: oh right, for some reason you're using
Do you mean it fixes the issue when you remove the mapping?
Do you mean mapped? In any case, yes I think that map should not map many database types to the same DBAL type, unless the schema manager code is able to adjust DBAL type options so the database type can be found back when going the other way. |
@greg0ire Yes, the idea is to trick DBAL without creating a separate custom type class. You might be surprised that the Symfony documentation suggests the same solution.
Yes, exactly. This way, in DBAL3 + ORM, developers tricked DBAL to use an unknown data type without creating and registering a custom class. To be precise, DBAL started this first by adding this line: dbal/src/Platforms/PostgreSQLPlatform.php Line 706 in 9042447
No, that's a drastic solution. The Doctrine team needs to decide if it's okay to trick DBAL or not. If not, then all these types should be removed, and developers should create them using custom types without using tricks. doctrine:
dbal:
mapping_types:
inet: override_inet
types:
override_inet: { class: 'App\Entity\InetType' }
Yes and no. It's more like masking a certain type as a string, with the intention of tricking Doctrine into not changing the schema, leaving the unknown type in the table schema. UPD: |
My personal opinion is that we should stop tricking DBAL, given how much confusion this causes, and given we no longer support reverse-engineering (the only use case I know for introspecting the database is diffing). I'd rather have the community create extra packages supporting extra types and automating the solution you showed above. I'd like to know what other maintainers think. |
<!-- Fill in the relevant information below to help triage your pull request. --> | Q | A |------------- | ----------- | Type | feature #### Summary Recreated PR #6467 for branch 4.1. This PR adds support for the `REAL` type for all DBMS, thereby resolving issues with partial support and potential bugs related to the `REAL` type in SQL schemas during migration creation. I've tried to explain this issue in detail through the `INET` type here #6466. Checked DBMS: - [x] PostgreSQL (represents `REAL` as `float4` or `real`) - [x] MySQL/MariaDB (#6467 (comment)) - [x] MSSQL (represents `REAL` as `real`) - [x] Oracle (represents `REAL` as `float(63)`) [doc ](https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlqr/Data-Types.html) - [x] IBM DB2 (represents `REAL` as `real`) - [x] SQLite (represents `REAL` as `real`)
This PR #6463 and this topic doctrine/migrations#1441 have highlighted a peculiar behavior.
In this case, let's consider the
inet
type, which was added to the PostgreSQL platform a long time ago -dbal/src/Platforms/PostgreSQLPlatform.php
Line 706 in 9042447
After some tests, I noticed that in DBAL3 and DBAL4 they behave strangely. I suspect that
inet
was added there to work around an issue because Doctrine did not recognize this type. That is, if we have such a migration in DBAL3:And such an entity:
Then DBAL3 will ignore the fact that the migration type is
INET
, deciding that it isVARCHAR
and will keep the type asINET
. However, in DBAL4, this trick no longer works, and we have to redefine the type as follows:So, my question, what function does
inet
perform ininitializeDoctrineTypeMappings()
or other similar custom types? And isn't this a bug? Or am I using or understanding it incorrectly?Therefore, I afraid that if the PR #6463 is applied to DBAL4 in the same way, it will not work correctly and will cause the same problems.
Thanks.
The text was updated successfully, but these errors were encountered: