Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
[DDC-2825] Fix persistence on a table with a schema on a platform without schema support #881
This PR solves two related issues with the use of a database schema on platforms (such as SQLite) that don't support schemas.
I discovered the issues when I generated the schema from my Doctrine entities on SQLite (for unit test purposes of my application) whereas my main application uses PostgreSQL.
This is one of my first PR on Doctrine, so sorry if I made some things in the wrong way and I'm open to discussion.
First problem: table names dots are not converted in the ORM
On a platform like SQLite, DBAL converts table names with dots (ie. a schema is declared) to double underscores.
And then somewhere in the code:
This doesn't work in the current version of Doctrine. The table is created as
Second problem: table names with reserved keywords in a database schema are not correctly escaped
When a table name is declared as
How this PR solves the problem
The classmetadata now stores in 2 separated properties the name of the table and the name of the schema. The schema property was partially implemented but I now make a full use of it.
When metadata is read (from Annotations, YAML, ...), if the table name has a dot (
This allows to do specific things about schemas everywhere in Doctrine, and not splitting again parts everywhere it's needed.
By the way, the
For instance, these 2 YAML configurations are valid and do the same thing:
This was something which was not finished to be implented since Doctrine 2.0.
The Default quote strategy now converts back the schema and table names to a unique table name, depending on the platform (e.g.
As a result, there is no problem anymore and entities can be persisted without getting any exception.
There's however a slight tradeoff on performance, as the
Again, this is one of my first PRs on Doctrine, so if there's anything wrong or if you have any question, feel free to comment this PR.
thank you for creating this pull request. I have automatically opened an issue
We use Jira to track the state of pull requests and the versions they got
Thank you @beberlei for your comments, this is now fixed!
I had to use a little workaround to avoid break compatibility issues on PostgreSQL, so that sequence names have the same before and after this PR changes.
As there is now a DBAL method to get the sequence name, based on table name and column name (see doctrine/dbal#428), I have to prepend the schema name to the table name before delegating the sequence name to DBAL. Maybe there should be a third optional argument for the schema name on the
Everything works fine, apart from the current build problem on the master branch.
If you have any other comment to improve the code, I'll be glad to help.
@michaelperrin @beberlei While I definitely like this PR I'm afraid this is a BC break because it will break receiving
Otherwise this PR would only fix one problem and probably introduce others for max identifier length and sequence name matching of existing tables.
@deeky666 Thank you for your comments. Tell me if I am wrong, but schema name was already included in sequence names before this PR.
As schemas were included as to define a schema, the table name had to be defined as
Still, you are right as there is a difference: the sequence name was
I like your second idea:
We keep this way full BC, and the
What do you think? If you think that's the way to go, I update this PR and open a PR on DBAL.
@michaelperrin Hmm I'm not getting entirely through this but you might be right. But what seems wrong is how the sequence name is now passed to the platform if the table name contans a schema prefix because it now contains an underscore instead of a dot. On PostgreSQL for example it was
@deeky666 Yes, this is what I realized with your previous comment, there is a change on the PostgreSQL platform.
@michaelperrin I am not sure if understand the root problem correctly but I'll try to explain my understanding. The problem is that table names that contain a dot do not work on platforms that do not support schemas/schema notation. Then my understanding is that this is a portability fix because why would you define your table names with dots then if you know that the platform does not support that kind of notation? If that is the case I would fix that entirely in ORM as you would not expect platforms that do not support this kind of notation to check for that and fix it by themselves. Then
@deeky666 Concerning your last comment, I'm going to try to make things a bit clearer.
The short answer: this PR aims to make ORM entities work on all platforms even when schemas are used, as the ORM is an abstraction layer.
Longer answer: Why is it useful to make schemas work on platforms that don't support them?
Here is my use case that made me discover the issue: my web project is developed on PostgreSQL and we make use of schemas (table names are therefore declared with dots).
I want to run unit tests of my project on a clean database. The idea is to create the schema structure in SQLite at the beginning of unit tests, run tests, and destroy the database. This currently doesn't work, as whereas DBAL is able to create the database structure (by emulating schemas), the ORM doesn't manage to read and save entities within this same database.
The ORM should be able to build structure and use entities for any database platform, based on the same database structure configuration (Annotations, YAML files, XML files, etc.). It works actually pretty fine, except this case.
This PR aim is twofold:
I hope it's a bit more clear.
@michaelperrin Thank you for that explanation. I think I get it now. So in my opinion you should use dotted notation if the underlying platform supports schemas, use double underscore for platforms that do not support schemas but can emulate. This leaves the question open about platforms that do neither support nor emulate schemas. Is the dotted notation acceptable here on all platforms? As for MySQL it works because it qualifies the database instead. But what about the others? Is that notation acceptable on all platforms then? Another question I have is about the double underscore notation. Is that a convention by Doctrine for all schema emulating platforms or is it SQLite specific?
@deeky666 I have fixed the name of sequences for platforms that support schemas. They are now named like
SQLite is currently the only one platform emulating schemas and it uses double underscores (see the
I agree with you. This PR can be a first step that solves the current problem and gives better support of schemas, and then we should enhance
@beberlei What do you think about this PR? Do you think it can be merged and enhancements can be made later on on DBAL?
@Ocramius I made most of the changes you mentioned.
I updated the documentation for all mapping formats. It was not necessary to update the XSD file as it already mentioned the
I agree with you concerning the use of double underscores directly in the ORM, it should be handled directly by platforms in DBAL.
However, do you think we consider this PR as a first step?
I can then open a PR on DBAL to add a method like
Do you want me to do this already now, or after this PR is merged?
@Ocramius The failing test is indeed related to the latest DBAL merge. That will be fixed in #910
@guilhermeblanco There are a lot of little things to be careful about indeed. I think this PR solves (most?) problems, at least for platforms that don't support schemas like SQLite but with entities declared with a schema (so that that Doctrine remains cross-platform) as it is currently impossible to persist an entity.