Skip to content

Commit

Permalink
fix: fix entityManager.getId for custom join table
Browse files Browse the repository at this point in the history
getId currently returns undefined for an entity with composite primary
key if primary key columns also foreign keys with lazy relations,
for e.g., in a custom join table. This commit tries to fix that

Closes: typeorm#7736 (maybe)
  • Loading branch information
ranjan-purbey committed Feb 24, 2022
1 parent 1f54c70 commit 0bd9641
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/metadata/ColumnMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,12 @@ export class ColumnMetadata {
return Object.keys(map).length > 0 ? map : undefined;

} else { // no embeds - no problems. Simply return column property name and its value of the entity
if (this.relationMetadata && entity[this.relationMetadata.propertyName] && entity[this.relationMetadata.propertyName] instanceof Object) {
/**
* Object.getOwnPropertyDescriptor checks if the relation is lazy, in which case value is a Promise
* DO NOT use `entity[this.relationMetadata.propertyName] instanceof Promise`, which will invoke property getter and make unwanted DB request
* refer: https://github.com/typeorm/typeorm/pull/8676#issuecomment-1049906331
*/
if (this.relationMetadata && !Object.getOwnPropertyDescriptor(entity, this.relationMetadata.propertyName)?.get && entity[this.relationMetadata.propertyName] && entity[this.relationMetadata.propertyName] instanceof Object) {
const map = this.relationMetadata.joinColumns.reduce((map, joinColumn) => {
const value = joinColumn.referencedColumn!.getEntityValueMap(entity[this.relationMetadata!.propertyName]);
if (value === undefined) return map;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Column, Entity, PrimaryGeneratedColumn } from "../../../../src";

@Entity()
export class Category {
@PrimaryGeneratedColumn("increment")
id!: number;

@Column()
name!: string;
}
10 changes: 10 additions & 0 deletions test/other-issues/get-id-for-composite-primary-key/entity/Post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Column, Entity, PrimaryGeneratedColumn } from "../../../../src";

@Entity()
export class Post {
@PrimaryGeneratedColumn("increment")
id!: number;

@Column()
content!: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {
CreateDateColumn,
Entity,
ManyToOne,
PrimaryColumn,
} from "../../../../src";
import { Category } from "./Category";
import { Post } from "./Post";

@Entity()
export class PostCategory {
@ManyToOne(() => Post)
post!: Promise<Post>;
@PrimaryColumn()
postId!: Post["id"];

@ManyToOne(() => Category)
category!: Promise<Category>;
@PrimaryColumn()
categoryId!: Category["id"];

@CreateDateColumn()
added!: Date;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { expect } from "chai";
import "reflect-metadata";
import { Connection } from "../../../src/connection/Connection";
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils";
import { Category } from "./entity/Category";
import { Post } from "./entity/Post";
import { PostCategory } from "./entity/PostCategory";

describe("other issues > getId should not return undefined for composite primary keys with lazy relations", () => {
let connections: Connection[];
before(
async () =>
(connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
}))
);
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));

it("getId should not return undefined", () =>
Promise.all(
connections.map(async ({ manager }) => {
const post = manager.create(Post, {
content: "Sample Post",
});
await manager.save(post);

const category = manager.create(Category, {
name: "javascript",
});
await manager.save(category);

const postCategory = manager.create(PostCategory, {});
postCategory.post = Promise.resolve(post);
postCategory.category = Promise.resolve(category);
await manager.save(postCategory);

expect(manager.getId(post)).not.to.be.undefined;
expect(manager.getId(category)).not.to.be.undefined;
expect(manager.getId(postCategory)).not.to.be.undefined;
})
));
});

0 comments on commit 0bd9641

Please sign in to comment.