Skip to content
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

Awaiting on OneToMany relations in child entities produces inaccurate results. #7841

Open
2 of 21 tasks
itsmefreitas opened this issue Jul 5, 2021 · 4 comments
Open
2 of 21 tasks

Comments

@itsmefreitas
Copy link

itsmefreitas commented Jul 5, 2021

Issue Description

Expected Behavior

When querying a child entity's relation where tuples that satisfy said relation exist in the database, an array containing said tuples' data mapped into regular objects should be returned instead of the empty array.

Actual Behavior

In the case where the specification for two separate child entities inherits a set of fields off a common entity and each of the two child entities both define a field f, corresponding to a @OneToMany relation r1 for the first entity and another @OneToMany relation r2 for the second entity, the following behaviour is observable:

  • Querying data for r1 (the first relation of the first entity) in an instance of the first child entity will correctly retrieve the records and populate an array with them;
  • Querying data for r2 (the second relation of the second entity) in an instance of the second child entity will always result inn an empty array;
  • Performing a reverse lookup on the entity mentioned by the relation r2 will properly yield the content that should have been in the @OneToMany relation for the instance of the second entity.

Steps to Reproduce

This is a minimum reproducible example in the necessary detail as to help discussion and provide context for the issue at hand:

  1. Take the following parent entity specification:
@Entity()
@TableInheritance({ column: { type: 'varchar', name: 'type' } })
export class ParentEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string

  @Column({ nullable: false })
  type: string
}
  1. Consider FirstChildEntity:
@ChildEntity()
export class FirstChildEntity extends ParentEntity {
  @Column({ nullable: true })
  someField: string

  @OneToMany(() => FirstMentionedEntity, (relationData) => relationData.firstChildEntity, { lazy: true })
  relationProperty: Promise<FirstMentionedEntity[]>
}
  1. Consider SecondChildEntity:
@ChildEntity()
export class SecondChildEntity extends ParentEntity {
  @Column({ nullable: true })
  someOtherField: string

  @OneToMany(() => SecondMentionedEntity, (relationData) => relationData.secondChildEntity, { lazy: true })
  relationProperty: Promise<SecondMentionedEntity[]>
}
  1. Let us now look at the definition for FirstMentionedEntity:
@Entity()
export class FirstMentionedEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string

  @ManyToOne(() => FirstChildEntity, {
    lazy: true,
    onDelete: 'CASCADE',
    nullable: false,
  })
  childEntity: Promise<FirstChildEntity>

  @Column({ nullable: false })
  someProperty: string
}
  1. Similarly, considering SecondMentionedEntity to have a similar shape/definition:
@Entity()
export class SecondMentionedEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string

  @ManyToOne(() => SecondChildEntity, {
    lazy: true,
    onDelete: 'CASCADE',
    nullable: false,
  })
  childEntity: Promise<SecondChildEntity>

  @Column({ nullable: false })
  someProperty: string
}
  1. Assume that data is present to satisfy relationProperty in one instance of FirstChildEntity and one of SecondChildEntity:
  • Awaiting on instance1.relationProperty will always retrieve the existing correct data from the database;
  • Awaiting on instance2.relationProperty will always result in an empty array, regardless of data for said relation being present in the database.

My Environment

Dependency Version
Operating System macOS Big Sur Version 11.3.1 (20E241)
Node.js version v15.14.0
Typescript version v4.2.3
TypeORM version v0.2.24

Additional Context

Important: In the example above, the relevant relation was specified through the class property relationProperty for both child entities, if we change the property name for just one of the entities then the relation data is correctly retrieved from the database.

Relevant Database Driver(s)

  • aurora-data-api
  • aurora-data-api-pg
  • better-sqlite3
  • cockroachdb
  • cordova
  • expo
  • mongodb
  • mysql
  • nativescript
  • oracle
  • postgres
  • react-native
  • sap
  • sqlite
  • sqlite-abstract
  • sqljs
  • sqlserver

Are you willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time, and I know how to start.
  • Yes, I have the time, but I don't know how to start. I would need guidance.
  • No, I don't have the time, although I believe I could do it if I had the time...
  • No, I don't have the time and I wouldn't even know how to start.
@itsmefreitas
Copy link
Author

Update: upon consulting the ORM logs, I noticed that when awaiting on relationProperty for SecondChildEntity, the resulting PSQL query will FROM the wrong table, i.e. the one for FirstMentionedEntity.

In essence, the query for the second instance's relationProperty retrieval will look like:

SELECT (...) FROM "first_child_entity" "relationProperty" WHERE "relationProperty"."childEntityId" IN ($1)

Which mentions the table name for FirstChildEntity.

@pleerock
Copy link
Member

table inheritance + lazy loading = killer combination

@itsmefreitas
Copy link
Author

table inheritance + lazy loading = killer combination

@pleerock, I believe that eager relations also show this behaviour, this was actually one of the things I tried to see if I could fix the problem, to no avail.

@itsmefreitas
Copy link
Author

@pleerock are there any updates on this issue, should I provide another example so it could help the discussion?

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

No branches or pull requests

2 participants