Skip to content

Loading…

DDC-511: Schema tool does not support STI - attempts to create a table per subclass #5019

Closed
doctrinebot opened this Issue · 7 comments

2 participants

@doctrinebot

Jira issue originally created by user @hobodave:

A recent update broke all support for STI.

Now the following does not work:

/****
 * @MappedSuperclass
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({"User" = "User", "Group" = "Group"})
 * @Table(name="user")
 */
abstract class Principal
{}
/****
 * @Entity
 */
class Group extends Principal
{}
/****
 * @Entity
 */
class User extends Principal
{}

Attempting to use orm:schema-tool:create results in the following error:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Group (user_id INT NOT NULL, username VARCHAR(45) NOT NULL, password VARCHAR(40)' at line 1

The SQL generated is:

CREATE TABLE Group (userid INT NOT NULL, username VARCHAR(45) NOT NULL, password VARCHAR(40) NOT NULL, status SMALLINT NOT NULL, firstname VARCHAR(45) NOT NULL, lastname VARCHAR(45) NOT NULL, email VARCHAR(60) NOT NULL, phone VARCHAR(20) DEFAULT NULL, pager VARCHAR(20) DEFAULT NULL, reset_code VARCHAR(6) DEFAULT NULL, is_password_expired TINYINT(1) NOT NULL, failed_login_count SMALLINT NOT NULL, is_admin TINYINT(1) NOT NULL, version INT DEFAULT 1 NOT NULL, UNIQUE INDEX Group_username_uniq (username), PRIMARY KEY(userid)) ENGINE = InnoDB;

CREATE TABLE User (userid INT NOT NULL, username VARCHAR(45) NOT NULL, password VARCHAR(40) NOT NULL, status SMALLINT NOT NULL, firstname VARCHAR(45) NOT NULL, lastname VARCHAR(45) NOT NULL, email VARCHAR(60) NOT NULL, phone VARCHAR(20) DEFAULT NULL, pager VARCHAR(20) DEFAULT NULL, reset_code VARCHAR(6) DEFAULT NULL, is_password_expired TINYINT(1) NOT NULL, failed_login_count SMALLINT NOT NULL, is_admin TINYINT(1) NOT NULL, version INT DEFAULT 1 NOT NULL, UNIQUE INDEX User_username_uniq (username), PRIMARY KEY(userid)) ENGINE = InnoDB;

@doctrinebot

Comment created by @guilhermeblanco:

That seems to be a reserved keyword issues.
I see comments around the STI issues, but this one doesn't seem to be the case.

Try to use a different table name:

@Table(name="groups")

and...

@Table(name="users")

This should fix the issue.

Cheers,

@doctrinebot

Comment created by @hobodave:

No. This is a STI problem. I don't want two different tables. Users and Groups are meant to share the same table "user". This worked prior to the omega CLI changes.

@doctrinebot

Comment created by romanb:

After thinking about this a while, I think it is an interesting problem that points out some conceptual issues as well as some opportunities. The reason SchemaTool behaves that way is simple, I think: A mapped superclass is nothing more than a regular php class that inherits its mapping information to the child classes "as if it were defined directly on the child classes". It is mainly a way to "reuse" mapping information without copy/paste. So the example given in the issue description is pretty much the same as this:

abstract class Principal
{}
/****
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({"User" = "User", "Group" = "Group"})
 * @Table(name="user")
 */
class Group extends Principal
{}
/****
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({"User" = "User", "Group" = "Group"})
 * @Table(name="user")
 */
 */
class User extends Principal
{}

Hence why it wants to create two tables. However, something else is also probably wrong because it should rather result in an error due to creating the same table twice ("user"). So deriving @Table from a mapped superclass seems to be uncharted territory also. How/Why this ever worked before as you say is still a mystery to me. Do you know by any chance a revision or tag (alpha4?) where this worked so that we can compare to that?

As you already found out, making the parent class an @Entity should work fine. We need to think more about how to deal with inheritance mapping information derived from mapped superclasses. For example, what should happen if we take the original example in the issue description but use JOINED instead like this:

/****
 * @MappedSuperclass
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({"User" = "User", "Group" = "Group"})
 */
abstract class Principal
{}
/****
 * @Entity
 */
class Group extends Principal
{}
/****
 * @Entity
 */
class User extends Principal
{}

Can this ever work or does it even make sense? Rewriting it to reflect what it actually "looks like" for Doctrine:

abstract class Principal
{}
/****
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({"User" = "User", "Group" = "Group"})
 */
class Group extends Principal
{}
/****
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({"User" = "User", "Group" = "Group"})
 */
class User extends Principal
{}

I think this would make no sense at all. Hence the combination of @MappedSuperclass @InheritanceType probably only seems to make sense currently in the SINGLE_TABLE scenario mentioned in the issue description.

An interesting possibility I noticed due to this ticket is that you can indeed use different inheritance mapping strategies in the same hierarchy, as long as the different subtrees of the hierarchy that are mapped with different strategies do not have a common ancestor entity. (For Doctrine the subtrees are then simply unrelated hierarchies, it does not care about common ancestor classes that are regular php classes). We should write some tests for that and add it to the docs, I will create a new ticket for that. Example:

class Base {}
class RootOfTreeA extends Base {} // Entity </ins> SINGLE_TABLE
class RootOfTreeB extends Base {} // Entity + JOINED
@doctrinebot

Comment created by romanb:

A solution and/or documented behavior for this should be evaluated before entering RC1.

@doctrinebot

Comment created by @beberlei:

MappedSuperclass Inheritance Details are confusing and are ignored now.

@doctrinebot

Issue was closed with resolution "Fixed"

@beberlei beberlei was assigned by doctrinebot
@doctrinebot doctrinebot added this to the 2.0-RC1 milestone
@doctrinebot doctrinebot closed this
@doctrinebot doctrinebot added the Bug label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.