-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: return 'null' (instead of 'undefined') on lazy relations that ha…
…ve no results (#7146) (#7147) Fix an issue where a lazy relation returns a Promise that resolves to 'undefined'. As implied by documentation, if the database has a NULL or no results, the result should be a literal 'null' in Javascript. Also added units tests to hilight the three scenarios in which this occurred. Closes #7146
- Loading branch information
1 parent
cc044a9
commit 9b278c9
Showing
4 changed files
with
143 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn } from "../../../../src"; | ||
import { Post } from "./Post"; | ||
|
||
@Entity() | ||
export class Category { | ||
|
||
@PrimaryGeneratedColumn() | ||
id: number; | ||
|
||
@OneToOne(type => Post, post => post.lazyOneToOne, { nullable: true, eager: false }) | ||
@JoinColumn() | ||
backRef1: Post; | ||
|
||
@OneToOne(type => Post, post => post.eagerOneToOne, { nullable: true, eager: false }) | ||
@JoinColumn() | ||
backRef2: Post; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { Entity, JoinColumn, ManyToOne, OneToOne, PrimaryGeneratedColumn } from "../../../../src"; | ||
import { Category } from "./Category"; | ||
|
||
@Entity() | ||
export class Post { | ||
|
||
@PrimaryGeneratedColumn() | ||
id: number; | ||
|
||
@ManyToOne(type => Category, { nullable: true, eager: false }) | ||
lazyManyToOne: Promise<Category | null>; | ||
|
||
@ManyToOne(type => Category, { nullable: true, eager: true }) | ||
eagerManyToOne: Category | null; | ||
|
||
@OneToOne(type => Category, { nullable: true, eager: false }) | ||
@JoinColumn() | ||
lazyOneToOneOwner: Promise<Category | null>; | ||
|
||
@OneToOne(type => Category, { nullable: true, eager: true }) | ||
@JoinColumn() | ||
eagerOneToOneOwner: Category | null; | ||
|
||
// Not a column; actual value is stored on the other side of this relation | ||
@OneToOne(type => Category, category => category.backRef1, { eager: false }) | ||
lazyOneToOne: Promise<Category | null>; | ||
|
||
// Not a column; actual value is stored on the other side of this relation | ||
@OneToOne(type => Category, category => category.backRef2, { eager: true }) | ||
eagerOneToOne: Category | null; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import "reflect-metadata"; | ||
import { createTestingConnections, closeTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; | ||
import { Connection } from "../../../src/connection/Connection"; | ||
import { expect } from "chai"; | ||
import { Post } from "./entity/Post"; | ||
|
||
describe("github issues > #7146 Lazy relations resolve to 'undefined' instead of 'null'", () => { | ||
|
||
let connections: Connection[]; | ||
before(async () => connections = await createTestingConnections({ | ||
entities: [__dirname + "/entity/*{.js,.ts}"], | ||
schemaCreate: true, | ||
dropSchema: true, | ||
})); | ||
beforeEach(() => reloadTestingDatabases(connections)); | ||
after(() => closeTestingConnections(connections)); | ||
|
||
async function prepareData(connection: Connection) { | ||
const savedPost = new Post(); | ||
await connection.manager.save(savedPost); | ||
} | ||
|
||
// The following 3 tests hilight the reported issue. | ||
// The remaining 6 tests were already succeeding before, but are included for completeness sake. | ||
|
||
describe("lazy-loaded relations", () => { | ||
|
||
it("should return null if ManyToOne relation has NULL in database", () => Promise.all(connections.map(async connection => { | ||
await prepareData(connection); | ||
const post = (await connection.manager.findOneOrFail(Post, 1)); | ||
expect(await post.lazyManyToOne).to.be.null; | ||
}))); | ||
|
||
it("should return null if OneToOne+JoinColumn relation has NULL in database", () => Promise.all(connections.map(async connection => { | ||
await prepareData(connection); | ||
const post = (await connection.manager.findOneOrFail(Post, 1)); | ||
expect(await post.lazyOneToOneOwner).to.be.null; | ||
}))); | ||
|
||
it("should return null if OneToOne relation has NULL in database", () => Promise.all(connections.map(async connection => { | ||
await prepareData(connection); | ||
const post = (await connection.manager.findOneOrFail(Post, 1)); | ||
expect(await post.lazyOneToOne).to.be.null; | ||
}))); | ||
|
||
}); | ||
|
||
describe("lazy-loaded relations included in 'relations' find option", () => { | ||
|
||
it("should return null if ManyToOne relation has NULL in database", () => Promise.all(connections.map(async connection => { | ||
await prepareData(connection); | ||
const post = (await connection.manager.findOneOrFail(Post, 1, { relations: ['lazyManyToOne'] })); | ||
expect(await post.lazyManyToOne).to.be.null; | ||
}))); | ||
|
||
it("should return null if OneToOne+JoinColumn relation has NULL in database", () => Promise.all(connections.map(async connection => { | ||
await prepareData(connection); | ||
const post = (await connection.manager.findOneOrFail(Post, 1, { relations: ['lazyOneToOneOwner'] })); | ||
expect(await post.lazyOneToOneOwner).to.be.null; | ||
}))); | ||
|
||
it("should return null if OneToOne relation has NULL in database", () => Promise.all(connections.map(async connection => { | ||
await prepareData(connection); | ||
const post = (await connection.manager.findOneOrFail(Post, 1, { relations: ['lazyOneToOne'] })); | ||
expect(await post.lazyOneToOne).to.be.null; | ||
}))); | ||
|
||
}); | ||
|
||
describe("eager-loaded relations", () => { | ||
|
||
it("should return null if ManyToOne relation has NULL in database", () => Promise.all(connections.map(async connection => { | ||
await prepareData(connection); | ||
const post = (await connection.manager.findOneOrFail(Post, 1)); | ||
expect(post.eagerManyToOne).to.be.null; | ||
}))); | ||
|
||
it("should return null if OneToOne+JoinColumn relation has NULL in database", () => Promise.all(connections.map(async connection => { | ||
await prepareData(connection); | ||
const post = (await connection.manager.findOneOrFail(Post, 1)); | ||
expect(post.eagerOneToOneOwner).to.be.null; | ||
}))); | ||
|
||
it("should return null if OneToOne relation has NULL in database", () => Promise.all(connections.map(async connection => { | ||
await prepareData(connection); | ||
const post = (await connection.manager.findOneOrFail(Post, 1)); | ||
expect(post.eagerOneToOne).to.be.null; | ||
}))); | ||
|
||
}); | ||
|
||
}); |