Skip to content

Commit

Permalink
fix: update/delete/softDelete by criteria of condition objects
Browse files Browse the repository at this point in the history
  • Loading branch information
maxbronnikov10 authored and maxbronnikov10 committed Jan 28, 2025
1 parent 79960e1 commit 6f5337d
Show file tree
Hide file tree
Showing 4 changed files with 287 additions and 9 deletions.
18 changes: 13 additions & 5 deletions src/entity-manager/EntityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export class EntityManager {

/**
* Executes raw SQL query and returns raw database results.
*
*
* @see [Official docs](https://typeorm.io/entity-manager-api) for examples.
*/
async query<T = any>(query: string, parameters?: any[]): Promise<T> {
Expand Down Expand Up @@ -778,7 +778,9 @@ export class EntityManager {
typeof criteria === "string" ||
typeof criteria === "number" ||
criteria instanceof Date ||
Array.isArray(criteria)
(Array.isArray(criteria) &&
typeof criteria[0] !== "object" &&
criteria[0] !== null)
) {
return this.createQueryBuilder()
.update(target)
Expand Down Expand Up @@ -832,7 +834,9 @@ export class EntityManager {
typeof criteria === "string" ||
typeof criteria === "number" ||
criteria instanceof Date ||
Array.isArray(criteria)
(Array.isArray(criteria) &&
typeof criteria[0] !== "object" &&
criteria[0] !== null)
) {
return this.createQueryBuilder()
.delete()
Expand Down Expand Up @@ -886,7 +890,9 @@ export class EntityManager {
typeof criteria === "string" ||
typeof criteria === "number" ||
criteria instanceof Date ||
Array.isArray(criteria)
(Array.isArray(criteria) &&
typeof criteria[0] !== "object" &&
criteria[0] !== null)
) {
return this.createQueryBuilder()
.softDelete()
Expand Down Expand Up @@ -940,7 +946,9 @@ export class EntityManager {
typeof criteria === "string" ||
typeof criteria === "number" ||
criteria instanceof Date ||
Array.isArray(criteria)
(Array.isArray(criteria) &&
typeof criteria[0] !== "object" &&
criteria[0] !== null)
) {
return this.createQueryBuilder()
.restore()
Expand Down
12 changes: 8 additions & 4 deletions src/repository/Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ export class Repository<Entity extends ObjectLiteral> {
| Date[]
| ObjectId
| ObjectId[]
| FindOptionsWhere<Entity>,
| FindOptionsWhere<Entity>
| FindOptionsWhere<Entity>[],
partialEntity: QueryDeepPartialEntity<Entity>,
): Promise<UpdateResult> {
return this.manager.update(
Expand Down Expand Up @@ -399,7 +400,8 @@ export class Repository<Entity extends ObjectLiteral> {
| Date[]
| ObjectId
| ObjectId[]
| FindOptionsWhere<Entity>,
| FindOptionsWhere<Entity>
| FindOptionsWhere<Entity>[],
): Promise<DeleteResult> {
return this.manager.delete(this.metadata.target as any, criteria as any)
}
Expand All @@ -420,7 +422,8 @@ export class Repository<Entity extends ObjectLiteral> {
| Date[]
| ObjectId
| ObjectId[]
| FindOptionsWhere<Entity>,
| FindOptionsWhere<Entity>
| FindOptionsWhere<Entity>[],
): Promise<UpdateResult> {
return this.manager.softDelete(
this.metadata.target as any,
Expand All @@ -444,7 +447,8 @@ export class Repository<Entity extends ObjectLiteral> {
| Date[]
| ObjectId
| ObjectId[]
| FindOptionsWhere<Entity>,
| FindOptionsWhere<Entity>
| FindOptionsWhere<Entity>[],
): Promise<UpdateResult> {
return this.manager.restore(
this.metadata.target as any,
Expand Down
18 changes: 18 additions & 0 deletions test/github-issues/10517/entity/Post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {
Column,
Entity,
PrimaryGeneratedColumn,
DeleteDateColumn,
} from "../../../../src"

@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number

@Column()
title: string

@DeleteDateColumn()
deletedDate: Date
}
248 changes: 248 additions & 0 deletions test/github-issues/10517/issue-10517.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
import "reflect-metadata"
import { expect } from "chai"
import { DataSource } from "../../../src/data-source/DataSource"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
import { Post } from "./entity/Post"

describe("github issues > #10517 EntityManager update/delete/softDelete don't work with list of where condition objects", function () {
// -------------------------------------------------------------------------
// Configuration
// -------------------------------------------------------------------------

let connections: DataSource[]
before(
async () =>
(connections = await createTestingConnections({
entities: [Post],
})),
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))

// -------------------------------------------------------------------------
// Specifications
// -------------------------------------------------------------------------

it("update by array of condition objects", () =>
Promise.all(
connections.map(async (connection) => {
const postRepository = connection.getRepository(Post)

// save a new posts
const newPost1 = postRepository.create()
newPost1.title = "Super post #1"
const newPost2 = postRepository.create()
newPost2.title = "Super post #2"
const newPost3 = postRepository.create()
newPost3.title = "Super post #3"
const newPost4 = postRepository.create()
newPost4.title = "Super post #4"

await postRepository.save(newPost1)
await postRepository.save(newPost2)
await postRepository.save(newPost3)
await postRepository.save(newPost4)

// update many
await postRepository.update(
[
{
title: "Super post #1",
},
{
title: "Super post #2",
},
],
{ title: "Super post" },
)

// load to check
const loadedPost1 = await postRepository.findOne({
where: {
id: 1,
},
})
const loadedPost2 = await postRepository.findOne({
where: {
id: 2,
},
})

// assert
expect(loadedPost1).to.be.eql({
id: 1,
title: "Super post",
deletedDate: null,
})

expect(loadedPost2).to.be.eql({
id: 2,
title: "Super post",
deletedDate: null,
})
}),
))

it("delete by array of condition objects", () =>
Promise.all(
connections.map(async (connection) => {
const postRepository = connection.getRepository(Post)

// save a new posts
const newPost1 = postRepository.create()
newPost1.title = "Super post #1"
const newPost2 = postRepository.create()
newPost2.title = "Super post #2"
const newPost3 = postRepository.create()
newPost3.title = "Super post #3"
const newPost4 = postRepository.create()
newPost4.title = "Super post #4"

await postRepository.save(newPost1)
await postRepository.save(newPost2)
await postRepository.save(newPost3)
await postRepository.save(newPost4)

// delete many
await postRepository.delete([
{
title: "Super post #1",
},
{
title: "Super post #2",
},
])

// load to check
const loadedPost1 = await postRepository.findOne({
where: {
id: 1,
},
})
const loadedPost2 = await postRepository.findOne({
where: {
id: 2,
},
})

// assert
expect(loadedPost1).to.be.eql(null)

expect(loadedPost2).to.be.eql(null)
}),
))

it("soft delete by array of condition objects", () =>
Promise.all(
connections.map(async (connection) => {
const postRepository = connection.getRepository(Post)

// save a new posts
const newPost1 = postRepository.create()
newPost1.title = "Super post #1"
const newPost2 = postRepository.create()
newPost2.title = "Super post #2"
const newPost3 = postRepository.create()
newPost3.title = "Super post #3"
const newPost4 = postRepository.create()
newPost4.title = "Super post #4"

await postRepository.save(newPost1)
await postRepository.save(newPost2)
await postRepository.save(newPost3)
await postRepository.save(newPost4)

// delete many
await postRepository.softDelete([
{
title: "Super post #1",
},
{
title: "Super post #2",
},
])

// load to check
const loadedPost1 = await postRepository.findOne({
where: {
id: 1,
},
})
const loadedPost2 = await postRepository.findOne({
where: {
id: 2,
},
})

// assert
expect(loadedPost1).to.be.eql(null)

expect(loadedPost2).to.be.eql(null)
}),
))

it("restore by array of condition objects", () =>
Promise.all(
connections.map(async (connection) => {
const postRepository = connection.getRepository(Post)

// save a new posts
const newPost1 = postRepository.create()
newPost1.title = "Super post #1"
const newPost2 = postRepository.create()
newPost2.title = "Super post #2"
const newPost3 = postRepository.create()
newPost3.title = "Super post #3"
const newPost4 = postRepository.create()
newPost4.title = "Super post #4"

await postRepository.save(newPost1)
await postRepository.save(newPost2)
await postRepository.save(newPost3)
await postRepository.save(newPost4)

const conditions = [
{
title: "Super post #1",
},
{
title: "Super post #2",
},
]

// update many
await postRepository.softDelete(conditions)

await postRepository.restore(conditions)

// load to check
const loadedPost1 = await postRepository.findOne({
where: {
id: 1,
},
})
const loadedPost2 = await postRepository.findOne({
where: {
id: 2,
},
})

// assert
expect(loadedPost1).to.be.eql({
id: 1,
title: "Super post #1",
deletedDate: null,
})

expect(loadedPost2).to.be.eql({
id: 2,
title: "Super post #2",
deletedDate: null,
})
}),
))
})

0 comments on commit 6f5337d

Please sign in to comment.