Skip to content

Conversation

jochen-jung
Copy link

Q A
Type bug
Fixed issues (doctrine/migrations#1460)

Summary

The schema was missing on the table name for MySQL.

Because of that "bin/console doctrine:migrations:diff" did not generate correct diffs and always detected the whole table as changed.

See:
doctrine/migrations#1460

Jochen Jung added 2 commits September 2, 2025 11:02
…d the whole table as changed instead of the true changes.
…d the whole table as changed instead of the true changes.
@derrabus
Copy link
Member

derrabus commented Sep 4, 2025

Looks like your change broke a lot of existing tests and you didn't add any new tests that would reproduce the issue that you're trying to solve. Are you planning to continue your work?

@jochen-jung
Copy link
Author

Hi, I was hoping for some feedback whether the change is fine this way in general, as I do not know the doctrine code well enough.

But I can try to resolve the unit tests first next Monday, if you prefer.

Jochen Jung added 4 commits September 8, 2025 08:35
…d the whole table as changed instead of the true changes.
…d the whole table as changed instead of the true changes.
…d the whole table as changed instead of the true changes.
…d the whole table as changed instead of the true changes.
@jochen-jung
Copy link
Author

I got the tests fixed now.

As I prepend the schema to the table name only for MySQL (I don't know if that makes sense for other engines as well), I added some ifs to the tests, so in case of MySQL the schema is prepended in the test as well.

For the tests/Functional/Schema/SchemaManagerFunctionalTestCase.php I overwrite the problematic tests now inside tests/Functional/Schema/MySQLSchemaManagerTest.php with a version that prepends the schema.

As for the change in src, another option would be instead of doing the concat on the database it could be done in the _getPortableTableDefinition() method instead, if that is considered cleaner. But I decided against that, as the method is marked as deprecated.

@morozov
Copy link
Member

morozov commented Sep 10, 2025

The DBAL doesn't support schemas on MySQL since it's a synonym for databases. Furthermore, on those platforms where the DBAL supports schemas (PostgreSQL, SQL Server), the current schema name is omitted from the introspected name. Thus, if the model defines the table name as users, it's created as public.users but then is introspected again as users.

What makes you think that this change needs to be made in the DBAL?

@jochen-jung
Copy link
Author

jochen-jung commented Sep 10, 2025

We have a project with MySql that has tables on different schemata (or tables in different tables, if schema and table is the same thing).

schemaA.table1
schemaA.table2
schemaB.table1
...

On the entities we have:
ORM\Table(name: 'table1', schema: 'schemaA')

And that is what is not working. For if I now generate the migration using
bin/console doctrine:migrations:diff
it detects the whole entity as new and not only the field that I modified. Same for indexes, foreign keys, ...

Also using ORM\Table(name: 'schemaA.table1') leads to the same error.

The patch I provided fixes this.
It then works with
ORM\Table(name: 'table1', schema: 'schemaA')

and generates a correct migration, that only contains the one change I did in the entity.

I believe that this is only an issue when a project uses more than one schema. If everything is inside the default schema, then it is no issue and it is enough to say 'table1', but in our case where there are different schemas inside a single project the schema name needs to be prepended to the table name.

@morozov
Copy link
Member

morozov commented Sep 10, 2025

We have a project with MySql that has tables on different schemata (or tables in different tables, if schema and table is the same thing).

schemaA.table1
schemaA.table2
schemaB.table1

This is not supported. The DBAL can introspect only a single MySQL database (which is a synonym for schema in MySQL) at a time. See the code:

protected function selectTableColumns(string $databaseName, ?string $tableName = null): Result
{
// The schema name is passed multiple times as a literal in the WHERE clause instead of using a JOIN condition
// in order to avoid performance issues on MySQL older than 8.0 and the corresponding MariaDB versions
// caused by https://bugs.mysql.com/bug.php?id=81347
$conditions = ['c.TABLE_SCHEMA = ?', 't.TABLE_SCHEMA = ?'];
$params = [$databaseName, $databaseName];

@jochen-jung
Copy link
Author

Then why not support it?

I understand that you can not support it the way you support schemas on other engines.

But to me it looks like all that is needed, is to add the schema to the tables names like in this pull request. Then it could be supported.

At least in the migrations:diff it works then. I don't have enough overview over the doctrine/dbal to know where else stuff would be affected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants