Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: support More/LessThanOrEqual in relations (#9978)
* test(select-buildwhere): exercise More/LessThanOrEqual for relations Extract the relevant test suite from functional/find-options, modifying the tests to use the equivalent More/LessThanOrEqual operators * fix(select-buildwhere): support More/LessThanOrEqual for relations Tweak `buildWhere()` to recognise more find operators and output the SQL equivalent - Recognise `moreThanOrEqual` and `lessThanOrEqual`, in addition to `moreThan` and `lessThan` - If the find operator ends with `OrEqual`, append `=` to the SQL operator * code style change --------- Co-authored-by: Umed Khudoiberdiev <pleerock.me@gmail.com>
- Loading branch information
Showing
8 changed files
with
352 additions
and
3 deletions.
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,20 @@ | ||
import { Column, Entity, OneToMany, PrimaryColumn } from "../../../../src" | ||
import { Photo } from "./Photo" | ||
|
||
@Entity() | ||
export class Author { | ||
@PrimaryColumn() | ||
id: number | ||
|
||
@Column() | ||
firstName: string | ||
|
||
@Column() | ||
lastName: string | ||
|
||
@Column() | ||
age: number | ||
|
||
@OneToMany(() => Photo, (photo) => photo.author) | ||
photos: Photo[] | ||
} |
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,11 @@ | ||
import { Column, JoinTable, ManyToMany } from "../../../../src" | ||
import { Author } from "./Author" | ||
|
||
export class Counters { | ||
@Column() | ||
likes: number | ||
|
||
@ManyToMany(() => Author) | ||
@JoinTable() | ||
likedUsers: Author[] | ||
} |
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,17 @@ | ||
import { Column, Entity, ManyToOne, PrimaryColumn } from "../../../../src" | ||
import { Author } from "./Author" | ||
|
||
@Entity() | ||
export class Photo { | ||
@PrimaryColumn() | ||
id: number | ||
|
||
@Column() | ||
filename: string | ||
|
||
@Column() | ||
description: string | ||
|
||
@ManyToOne(() => Author, (author) => author.photos) | ||
author: Author | ||
} |
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,41 @@ | ||
import { | ||
Column, | ||
Entity, | ||
JoinTable, | ||
ManyToMany, | ||
ManyToOne, | ||
PrimaryColumn, | ||
} from "../../../../src" | ||
import { Tag } from "./Tag" | ||
import { Author } from "./Author" | ||
import { Counters } from "./Counters" | ||
|
||
@Entity() | ||
export class Post { | ||
@PrimaryColumn() | ||
id: number | ||
|
||
@Column() | ||
title: string | ||
|
||
@Column() | ||
text: string | ||
|
||
@ManyToMany(() => Tag, (tag) => tag.posts) | ||
@JoinTable() | ||
tags: Tag[] | ||
|
||
@ManyToOne(() => Author) | ||
author: Author | ||
|
||
@Column(() => Counters) | ||
counters: Counters | ||
|
||
toString() { | ||
return this.title | ||
} | ||
|
||
doSomething() { | ||
return 123 | ||
} | ||
} |
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,14 @@ | ||
import { Column, Entity, ManyToMany, PrimaryColumn } from "../../../../src" | ||
import { Post } from "./Post" | ||
|
||
@Entity() | ||
export class Tag { | ||
@PrimaryColumn() | ||
id: number | ||
|
||
@Column() | ||
name: string | ||
|
||
@ManyToMany(() => Post, (post) => post.tags) | ||
posts: 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,96 @@ | ||
import "reflect-metadata" | ||
import { EntityManager } from "../../../src" | ||
import { Post } from "./entity/Post" | ||
import { Author } from "./entity/Author" | ||
import { Photo } from "./entity/Photo" | ||
import { Tag } from "./entity/Tag" | ||
import { Counters } from "./entity/Counters" | ||
|
||
export async function prepareData(manager: EntityManager) { | ||
const photo1 = new Photo() | ||
photo1.id = 1 | ||
photo1.filename = "saw.jpg" | ||
photo1.description = "Me and saw" | ||
await manager.save(photo1) | ||
|
||
const photo2 = new Photo() | ||
photo2.id = 2 | ||
photo2.filename = "chain.jpg" | ||
photo2.description = "Me and chain" | ||
await manager.save(photo2) | ||
|
||
const user1 = new Author() | ||
user1.id = 1 | ||
user1.firstName = "Timber" | ||
user1.lastName = "Saw" | ||
user1.age = 25 | ||
user1.photos = [photo1, photo2] | ||
await manager.save(user1) | ||
|
||
const user2 = new Author() | ||
user2.id = 2 | ||
user2.firstName = "Gyro" | ||
user2.lastName = "Copter" | ||
user2.age = 52 | ||
user2.photos = [] | ||
await manager.save(user2) | ||
|
||
const tag1 = new Tag() | ||
tag1.id = 1 | ||
tag1.name = "category #1" | ||
await manager.save(tag1) | ||
|
||
const tag2 = new Tag() | ||
tag2.id = 2 | ||
tag2.name = "category #2" | ||
await manager.save(tag2) | ||
|
||
const tag3 = new Tag() | ||
tag3.id = 3 | ||
tag3.name = "category #3" | ||
await manager.save(tag3) | ||
|
||
const post1 = new Post() | ||
post1.id = 1 | ||
post1.title = "Post #1" | ||
post1.text = "About post #1" | ||
post1.author = user1 | ||
post1.tags = [tag1, tag2] | ||
post1.counters = new Counters() | ||
post1.counters.likes = 1 | ||
post1.counters.likedUsers = [user1] | ||
await manager.save(post1) | ||
|
||
const post2 = new Post() | ||
post2.id = 2 | ||
post2.title = "Post #2" | ||
post2.text = "About post #2" | ||
post2.author = user1 | ||
post2.tags = [tag2] | ||
post2.counters = new Counters() | ||
post2.counters.likes = 2 | ||
post2.counters.likedUsers = [user1, user2] | ||
await manager.save(post2) | ||
|
||
const post3 = new Post() | ||
post3.id = 3 | ||
post3.title = "Post #3" | ||
post3.text = "About post #3" | ||
post3.author = user2 | ||
post3.tags = [tag1] | ||
post3.counters = new Counters() | ||
post3.counters.likes = 1 | ||
post3.counters.likedUsers = [user2] | ||
await manager.save(post3) | ||
|
||
const post4 = new Post() | ||
post4.id = 4 | ||
post4.title = "Post #4" | ||
post4.text = "About post #4" | ||
post4.author = user1 | ||
post4.tags = [] | ||
post4.counters = new Counters() | ||
post4.counters.likes = 1 | ||
post4.counters.likedUsers = [user1] | ||
await manager.save(post4) | ||
} |
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,140 @@ | ||
import "reflect-metadata" | ||
import "../../utils/test-setup" | ||
import { DataSource, LessThanOrEqual, MoreThanOrEqual } from "../../../src" | ||
import { | ||
closeTestingConnections, | ||
createTestingConnections, | ||
reloadTestingDatabases, | ||
} from "../../utils/test-utils" | ||
import { Author } from "./entity/Author" | ||
import { Post } from "./entity/Post" | ||
import { Tag } from "./entity/Tag" | ||
import { prepareData } from "./find-options-test-utils" | ||
|
||
describe("github issues > #9977", () => { | ||
let connections: DataSource[] | ||
before( | ||
async () => | ||
(connections = await createTestingConnections({ | ||
__dirname, | ||
})), | ||
) | ||
beforeEach(() => reloadTestingDatabases(connections)) | ||
after(() => closeTestingConnections(connections)) | ||
|
||
it("where relations with (More|Less)ThanOrEqual operators", () => | ||
Promise.all( | ||
connections.map(async (connection) => { | ||
await prepareData(connection.manager) | ||
|
||
const posts1 = await connection | ||
.createQueryBuilder(Post, "post") | ||
.setFindOptions({ | ||
where: { | ||
tags: MoreThanOrEqual(2), | ||
}, | ||
}) | ||
.getMany() | ||
posts1.should.be.eql([ | ||
{ | ||
id: 1, | ||
title: "Post #1", | ||
text: "About post #1", | ||
counters: { likes: 1 }, | ||
}, | ||
]) | ||
|
||
const posts2 = await connection | ||
.createQueryBuilder(Post, "post") | ||
.setFindOptions({ | ||
where: { | ||
tags: MoreThanOrEqual(1), | ||
counters: { | ||
likedUsers: MoreThanOrEqual(2), | ||
}, | ||
}, | ||
}) | ||
.getMany() | ||
posts2.should.be.eql([ | ||
{ | ||
id: 2, | ||
title: "Post #2", | ||
text: "About post #2", | ||
counters: { likes: 2 }, | ||
}, | ||
]) | ||
|
||
const posts3 = await connection | ||
.createQueryBuilder(Post, "post") | ||
.setFindOptions({ | ||
where: { | ||
author: { | ||
photos: MoreThanOrEqual(2), | ||
}, | ||
}, | ||
order: { | ||
id: "asc", | ||
}, | ||
}) | ||
.getMany() | ||
posts3.should.be.eql([ | ||
{ | ||
id: 1, | ||
title: "Post #1", | ||
text: "About post #1", | ||
counters: { likes: 1 }, | ||
}, | ||
{ | ||
id: 2, | ||
title: "Post #2", | ||
text: "About post #2", | ||
counters: { likes: 2 }, | ||
}, | ||
{ | ||
id: 4, | ||
title: "Post #4", | ||
text: "About post #4", | ||
counters: { likes: 1 }, | ||
}, | ||
]) | ||
|
||
const authors = await connection | ||
.createQueryBuilder(Author, "author") | ||
.setFindOptions({ | ||
where: { | ||
photos: MoreThanOrEqual(1), | ||
}, | ||
}) | ||
.getMany() | ||
authors.should.be.eql([ | ||
{ id: 1, firstName: "Timber", lastName: "Saw", age: 25 }, | ||
]) | ||
|
||
const tags1 = await connection | ||
.createQueryBuilder(Tag, "tag") | ||
.setFindOptions({ | ||
where: { | ||
posts: MoreThanOrEqual(2), | ||
}, | ||
order: { | ||
id: "asc", | ||
}, | ||
}) | ||
.getMany() | ||
tags1.should.be.eql([ | ||
{ id: 1, name: "category #1" }, | ||
{ id: 2, name: "category #2" }, | ||
]) | ||
|
||
const tags2 = await connection | ||
.createQueryBuilder(Tag, "tag") | ||
.setFindOptions({ | ||
where: { | ||
posts: LessThanOrEqual(0), | ||
}, | ||
}) | ||
.getMany() | ||
tags2.should.be.eql([{ id: 3, name: "category #3" }]) | ||
}), | ||
)) | ||
}) |