mirror of
https://github.com/doctrine/orm.git
synced 2026-03-23 22:42:18 +01:00
SQLite schema namespace adjustment incorrectly implied for ManyToMany inserts. #6601
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 @AlexHowansky on GitHub (Jan 6, 2021).
Many databases provide schema namespacing that can be used to segregate tables. The schema name can be prepended to the tablename with a namespace separator, typically a dot. For example, if you created the
USERStable in theAPPschema namespace, your select might look likeSELECT APP.USERS.ID FROM APP.USERS.Doctrine recognizes this dot notation for databases like Oracle that support schema namespaces. However, since SQLite does not, Doctrine translates
APP.USERStoAPP__USERSto provide a sort of faux namespacing. This feature works correctly when using migrations to create the table and when using Doctrine to query it, but is broken when inserting via a ManyToMany relationship.If all the following are true:
Then the table name of the join table is not translated to
SCHEMA__TABLEas expected, and the insert fails because it will incorrectly refer toSCHEMA.TABLE.For example, if we define a SQLite database in our
.envfile:DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"And create Student and Course entities like:
Then we can run migrations to create the database and we'll get the fake namespaced table names as expected:
We can successfully use the entities to create new rows:
And to query them:
However, we'll get an error if we create a relationship that would result in an insert to the join table:
Note in the query that Doctrine built above,
APP.COURSEhas been correctly translated intoAPP__COURSE, butAPP.COURSE_STUDENT_JOINhas not. This occurs only for inserts into ManyToMany join tables -- inserts into other tables and read queries on the join tables (e.g.,$jim->getCourses()) will be correctly translated.The above code can be made to work by either removing the schema namespaces from the Entity metadata definitions or changing the database driver to something that supports schema namespaces. Thus, there is a simple workaround when using a single database platform. However, applying this workaround makes the entities no longer transportable or agnostic, and prevents me (for example) from using Oracle for production and SQLite for test.
I've got a minimal repo here to demonstrate: https://github.com/AlexHowansky/doctrine_sqlite_bug
See the
src/Command/TestCommand.phpfile for an example containing the code noted here.doctrine:common 3.1.0
doctrine:dbal 2.12.1
doctrine:orm 2.8.1
@AlexHowansky commented on GitHub (Jan 11, 2021):
OK I think I found the problem.
Doctrine\ORM\Mapping\DefaultQuoteStrategy::getJoinTableName()only works if the schema name and the table name are specified separately:While
Doctrine\DBAL\Platforms\SqlitePlatformallows the schema name to be specified as part of the table name, via dot notation:It seems perhaps the intent was to allow changing the dot to two underscores after the full schema+table string had been built. Can dots be disallowed in table names based on the currently selected driver? I.e., disallowing dots in SQLite table names would force use of the explicit schema syntax, which avoids this issue.