fix: Delete before upsert in upsertWithReplace to handle relations with unique constraint (#7875)
This commit is contained in:
+75
-10
@@ -80,6 +80,10 @@ class Entity2 {
|
|||||||
@Property()
|
@Property()
|
||||||
title: string
|
title: string
|
||||||
|
|
||||||
|
@Unique()
|
||||||
|
@Property()
|
||||||
|
handle: string
|
||||||
|
|
||||||
@Property({ nullable: true })
|
@Property({ nullable: true })
|
||||||
deleted_at: Date | null
|
deleted_at: Date | null
|
||||||
|
|
||||||
@@ -279,6 +283,7 @@ describe("mikroOrmRepository", () => {
|
|||||||
const entity2 = {
|
const entity2 = {
|
||||||
id: "2",
|
id: "2",
|
||||||
title: "en2",
|
title: "en2",
|
||||||
|
handle: "some-handle",
|
||||||
entity1: { title: "en1" },
|
entity1: { title: "en1" },
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,6 +300,7 @@ describe("mikroOrmRepository", () => {
|
|||||||
it("should successfully create the parent entity of a many-to-one", async () => {
|
it("should successfully create the parent entity of a many-to-one", async () => {
|
||||||
const entity2 = {
|
const entity2 = {
|
||||||
id: "2",
|
id: "2",
|
||||||
|
handle: "some-handle",
|
||||||
title: "en2",
|
title: "en2",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,6 +331,7 @@ describe("mikroOrmRepository", () => {
|
|||||||
const entity2 = {
|
const entity2 = {
|
||||||
id: "2",
|
id: "2",
|
||||||
title: "en2",
|
title: "en2",
|
||||||
|
handle: "some-handle",
|
||||||
entity1: { id: "1" },
|
entity1: { id: "1" },
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,6 +364,7 @@ describe("mikroOrmRepository", () => {
|
|||||||
const entity2 = {
|
const entity2 = {
|
||||||
id: "2",
|
id: "2",
|
||||||
title: "en2",
|
title: "en2",
|
||||||
|
handle: "some-handle",
|
||||||
entity1: { id: "1" },
|
entity1: { id: "1" },
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,7 +435,10 @@ describe("mikroOrmRepository", () => {
|
|||||||
const entity1 = {
|
const entity1 = {
|
||||||
id: "1",
|
id: "1",
|
||||||
title: "en1",
|
title: "en1",
|
||||||
entity2: [{ title: "en2-1" }, { title: "en2-2" }],
|
entity2: [
|
||||||
|
{ title: "en2-1", handle: "some-handle" },
|
||||||
|
{ title: "en2-2", handle: "some-other-handle" },
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
const { performedActions: performedActions1 } =
|
const { performedActions: performedActions1 } =
|
||||||
@@ -477,7 +488,7 @@ describe("mikroOrmRepository", () => {
|
|||||||
const entity1 = {
|
const entity1 = {
|
||||||
id: "1",
|
id: "1",
|
||||||
title: "en1",
|
title: "en1",
|
||||||
entity2: [{ title: "en2-1", entity1: null }],
|
entity2: [{ title: "en2-1", handle: "some-handle", entity1: null }],
|
||||||
}
|
}
|
||||||
|
|
||||||
const { performedActions: performedActions1 } =
|
const { performedActions: performedActions1 } =
|
||||||
@@ -521,7 +532,10 @@ describe("mikroOrmRepository", () => {
|
|||||||
const entity1 = {
|
const entity1 = {
|
||||||
id: "1",
|
id: "1",
|
||||||
title: "en1",
|
title: "en1",
|
||||||
entity2: [{ title: "en2-1" }, { title: "en2-2" }],
|
entity2: [
|
||||||
|
{ title: "en2-1", handle: "some-handle" },
|
||||||
|
{ title: "en2-2", handle: "some-other-handle" },
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
const { entities: entities1, performedActions: performedActions1 } =
|
const { entities: entities1, performedActions: performedActions1 } =
|
||||||
@@ -540,7 +554,7 @@ describe("mikroOrmRepository", () => {
|
|||||||
deleted: {},
|
deleted: {},
|
||||||
})
|
})
|
||||||
|
|
||||||
entity1.entity2.push({ title: "en2-3" })
|
entity1.entity2.push({ title: "en2-3", handle: "some-new-handle" })
|
||||||
|
|
||||||
const { performedActions: performedActions2 } =
|
const { performedActions: performedActions2 } =
|
||||||
await manager1().upsertWithReplace([entity1], {
|
await manager1().upsertWithReplace([entity1], {
|
||||||
@@ -585,8 +599,8 @@ describe("mikroOrmRepository", () => {
|
|||||||
id: "1",
|
id: "1",
|
||||||
title: "en1",
|
title: "en1",
|
||||||
entity2: [
|
entity2: [
|
||||||
{ id: "2", title: "en2-1" },
|
{ id: "2", title: "en2-1", handle: "some-handle" },
|
||||||
{ id: "3", title: "en2-2" },
|
{ id: "3", title: "en2-2", handle: "some-other-handle" },
|
||||||
] as any[],
|
] as any[],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,7 +620,10 @@ describe("mikroOrmRepository", () => {
|
|||||||
deleted: {},
|
deleted: {},
|
||||||
})
|
})
|
||||||
|
|
||||||
entity1.entity2 = [{ id: "2", title: "newen2-1" }, { title: "en2-3" }]
|
entity1.entity2 = [
|
||||||
|
{ id: "2", title: "newen2-1" },
|
||||||
|
{ title: "en2-3", handle: "some-new-handle" },
|
||||||
|
]
|
||||||
|
|
||||||
const { entities: entities2, performedActions: performedActions2 } =
|
const { entities: entities2, performedActions: performedActions2 } =
|
||||||
await manager1().upsertWithReplace([entity1], {
|
await manager1().upsertWithReplace([entity1], {
|
||||||
@@ -653,6 +670,45 @@ describe("mikroOrmRepository", () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should update an entity with a one-to-many relation that has the same unique constraint key", async () => {
|
||||||
|
const entity1 = {
|
||||||
|
id: "1",
|
||||||
|
title: "en1",
|
||||||
|
entity2: [{ id: "2", title: "en2-1", handle: "some-handle" }] as any[],
|
||||||
|
}
|
||||||
|
|
||||||
|
await manager1().upsertWithReplace([entity1], {
|
||||||
|
relations: ["entity2"],
|
||||||
|
})
|
||||||
|
|
||||||
|
entity1.entity2 = [{ title: "newen2-1", handle: "some-handle" }]
|
||||||
|
await manager1().upsertWithReplace([entity1], {
|
||||||
|
relations: ["entity2"],
|
||||||
|
})
|
||||||
|
|
||||||
|
const listedEntities = await manager1().find({
|
||||||
|
where: { id: "1" },
|
||||||
|
options: { populate: ["entity2"] },
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(listedEntities).toHaveLength(1)
|
||||||
|
expect(listedEntities[0]).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: "1",
|
||||||
|
title: "en1",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
expect(listedEntities[0].entity2.getItems()).toHaveLength(1)
|
||||||
|
expect(listedEntities[0].entity2.getItems()).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
title: "newen2-1",
|
||||||
|
handle: "some-handle",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it("should only create the parent entity of a many-to-many if relation is not included", async () => {
|
it("should only create the parent entity of a many-to-many if relation is not included", async () => {
|
||||||
const entity1 = {
|
const entity1 = {
|
||||||
id: "1",
|
id: "1",
|
||||||
@@ -875,7 +931,12 @@ describe("mikroOrmRepository", () => {
|
|||||||
|
|
||||||
// The sub-entity upsert should happen after the main was created
|
// The sub-entity upsert should happen after the main was created
|
||||||
await manager2().upsertWithReplace([
|
await manager2().upsertWithReplace([
|
||||||
{ id: "2", title: "en2", entity1_id: mainEntity[0].id },
|
{
|
||||||
|
id: "2",
|
||||||
|
title: "en2",
|
||||||
|
handle: "some-handle",
|
||||||
|
entity1_id: mainEntity[0].id,
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const listedEntities = await manager1().find({
|
const listedEntities = await manager1().find({
|
||||||
@@ -910,7 +971,7 @@ describe("mikroOrmRepository", () => {
|
|||||||
const entity1 = {
|
const entity1 = {
|
||||||
id: "1",
|
id: "1",
|
||||||
title: "en1",
|
title: "en1",
|
||||||
entity2: [{ title: "en2" }],
|
entity2: [{ title: "en2", handle: "some-handle" }],
|
||||||
entity3: [{ title: "en3-1" }, { title: "en3-2" }] as any,
|
entity3: [{ title: "en3-1" }, { title: "en3-2" }] as any,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1050,7 +1111,11 @@ describe("mikroOrmRepository", () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
it("should map ForeignKeyConstraintViolationException MedusaError on upsertWithReplace", async () => {
|
it("should map ForeignKeyConstraintViolationException MedusaError on upsertWithReplace", async () => {
|
||||||
const entity2 = { title: "en2", entity1: { id: "1" } }
|
const entity2 = {
|
||||||
|
title: "en2",
|
||||||
|
handle: "some-handle",
|
||||||
|
entity1: { id: "1" },
|
||||||
|
}
|
||||||
const err = await manager2()
|
const err = await manager2()
|
||||||
.upsertWithReplace([entity2])
|
.upsertWithReplace([entity2])
|
||||||
.catch((e) => e.message)
|
.catch((e) => e.message)
|
||||||
|
|||||||
@@ -658,21 +658,10 @@ export function mikroOrmBaseRepositoryFactory<T extends object = object>(
|
|||||||
joinColumnsConstraints[joinColumn] = data[referencedColumnName]
|
joinColumnsConstraints[joinColumn] = data[referencedColumnName]
|
||||||
})
|
})
|
||||||
|
|
||||||
if (normalizedData.length) {
|
|
||||||
normalizedData.forEach((normalizedDataItem: any) => {
|
|
||||||
Object.assign(normalizedDataItem, {
|
|
||||||
...joinColumnsConstraints,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const { performedActions: performedActions_ } =
|
|
||||||
await this.upsertMany_(manager, relation.type, normalizedData)
|
|
||||||
this.mergePerformedActions(performedActions, performedActions_)
|
|
||||||
}
|
|
||||||
|
|
||||||
const toDeleteEntities = await manager.find<any>(
|
const toDeleteEntities = await manager.find<any>(
|
||||||
relation.type,
|
relation.type,
|
||||||
{
|
{
|
||||||
|
...joinColumnsConstraints,
|
||||||
id: { $nin: normalizedData.map((d: any) => d.id) },
|
id: { $nin: normalizedData.map((d: any) => d.id) },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -693,6 +682,18 @@ export function mikroOrmBaseRepositoryFactory<T extends object = object>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (normalizedData.length) {
|
||||||
|
normalizedData.forEach((normalizedDataItem: any) => {
|
||||||
|
Object.assign(normalizedDataItem, {
|
||||||
|
...joinColumnsConstraints,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const { performedActions: performedActions_ } =
|
||||||
|
await this.upsertMany_(manager, relation.type, normalizedData)
|
||||||
|
this.mergePerformedActions(performedActions, performedActions_)
|
||||||
|
}
|
||||||
|
|
||||||
return { entities: normalizedData, performedActions }
|
return { entities: normalizedData, performedActions }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user