Skip to content

Multiple ManyToOne relations to the same "Column Name" cause invalid SQL to be generated #10148

@KsaRedFx

Description

@KsaRedFx

Issue description

If you have 3 tables, where;

  • Table 1 has a unique PK, and JOIN references to Table 2 (using table1.table_2_key => table2.key, table1.table_3_key => table2.table_3_key) and Table 3 (using table1.table_3_key => table3.key)
  • Table 2 has a compound PK of (key, table_3_key), and JOIN references to Table 3 (using table2.table_3_key => table3.key)
  • Table 3 has a unique PK (key), and references to nothing.

Invalid SQL will be generated by TypeORM on findOne() but not on syncronize

Expected Behavior

All camelCase variables to be replaced with their snake_case/table definition names

Actual Behavior

Some fields are not properly replaced, or possibly not properly looked up from their source tables

Steps to reproduce

export abstract class Basics {
  @ManyToOne(() => Groups)
  @JoinColumn({ name: 'group_key' })
  group?: Groups;

  @Column({ name: 'group_key', length: 70, nullable: true })
  groupKey: string;

  @ManyToOne(() => Rounds, (round) => round.key)
  @JoinColumn([
    { name: 'round_key', referencedColumnName: 'key' },
    { name: 'group_key', referencedColumnName: 'groupKey' },
  ])
  round?: Rounds;

  @Column({ name: 'round_key', length: 70, nullable: true })
  roundKey: string;
}
@Entity({
  name: 'rounds',
})
export class Rounds {
  @PrimaryColumn({ name: 'key', length: 70, type: 'varchar' })
  key: string;

  @Column({ name: 'name', length: 100, type: 'varchar' })
  name: string;

  @ManyToOne(() => Groups, (group) => group.key)
  @JoinColumn({ name: 'group_key' })
  group?: Groups;

  @PrimaryColumn({ name: 'group_key' })
  groupKey: string;
}
@Entity({
  name: 'groups',
})
export class Groups {
  @PrimaryColumn({ name: 'key', length: 70, type: 'varchar' })
  key: string;

  @Column({ name: 'name', length: 70, type: 'varchar' })
  name: string;

  @Column({ name: 'type', length: 20, type: 'varchar' })
  type: GroupType;
  
  @OneToMany(() => Rounds, (round) => round.group)
  rounds: Rounds[];
}
export abstract class Basics {
  @ManyToOne(() => Groups)
  @JoinColumn({ name: 'group_key', referencedColumnName: 'key' })
  group?: Groups;

  @Column({ name: 'group_key', length: 70, nullable: true })
  groupKey: string;

  @ManyToOne(() => Rounds)
  @JoinColumn([
    { name: 'round_key', referencedColumnName: 'key' },
    { name: 'group_key', referencedColumnName: 'groupKey' },
  ])
  round?: Rounds;

  @Column({ name: 'round_key', length: 70, nullable: true })
  roundKey: string;
}

@Entity({
  name: 'servers',
})
export class Servers extends Basics {
  @PrimaryColumn({ name: 'uuid', length: 36, type: 'varchar' })
  uuid: string;
}
  const serverData = await conn.getRepository(Servers).findOne({ where: { uuid }, relations: ['group', 'round'] });

My Environment

Dependency Version
Operating System Linux
Node.js version v16.17.0
TypeORM version 0.3.17

Additional Context

This issue was introduced, I believe, because a join to Rounds has a compound primary key that uses a column name shared with another table join.

Setting the JoinColumn to key or group_key or anything of the sort, causes it to fail to come online when syncronize: true is set. So; for whatever reason, the camelCase groupKey is valid. However, having more than one JoinColumn definition for the same name causes TypeORM to get confused.

Once the SQL is generated for the request, it does properly replace groupKey with group_key for the rounds join, but NOT for the groups join, it produces

      LEFT JOIN `groups` `Servers__Servers_group` ON Servers__Servers_group.groupKey = `Servers`.`group_key` 
      LEFT JOIN `rounds` `Servers__Servers_round` ON `Servers__Servers_round`.`key` = `Servers`.`round_key` AND `Servers__Servers_round`.`group_key` = `Servers`.`group_key` 

The FKs and Indexes are all generated as expected, with composite primary keys. The only thing that does not generate properly is the SQL on SELECT.

Removing the extra item from the JoinColumn definition causes the FKs and Indexes to be generated incorrectly

ALTER TABLE `servers` ADD CONSTRAINT `FK_821...` FOREIGN KEY (`round_key`, `round_key`) REFERENCES `rounds`(`key`,`group_key`)

and in turn can cause SQL to throw a duplicate column error.

There seems to be a lack of documentation on exactly what I should be doing here, probably because it is an edge case. But if you edit the SQL manually to have the correct value of just key and run it, it does work as expected. My database explorer tools also seem capable of generating queries correctly based on this scenario and the FK/Index setup that TypeORM generates in this configuration.

Relevant Database Driver(s)

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

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

Yes, I have the time, but I don't know how to start. I would need guidance.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions