-
-
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: support combination of many-to-one/cacade/composte PK (#6417)
handle setting values deeply in entities with relations in ColumnMetadata, also check for a virtual relationship column in rawsqlresultstoentitytransformer this allows us to handle a case where `many-to-one` with explicit composite PKs columns were failing to persist a second time- instead of correctly updating the field they would cause an insert to occur leading to a unique PK constraint error
- Loading branch information
1 parent
7ec1b75
commit 9a0497b
Showing
7 changed files
with
219 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
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,52 @@ | ||
import { EntitySchema } from "../../../../src"; | ||
|
||
import PostTag from "./PostTag"; | ||
import PostAttachment from "./PostAttachment"; | ||
|
||
let id = 0; | ||
|
||
export default class Post { | ||
postId: number; | ||
|
||
otherId: number; | ||
|
||
tags: PostTag[]; | ||
|
||
attachments: PostAttachment[]; | ||
|
||
constructor() { | ||
this.postId = id++; | ||
this.otherId = id++; | ||
} | ||
} | ||
|
||
export const PostSchema = new EntitySchema<Post>({ | ||
name: "Post", | ||
target: Post, | ||
columns: { | ||
otherId: { | ||
type: Number, | ||
primary: true, | ||
nullable: false | ||
}, | ||
postId: { | ||
type: Number, | ||
primary: true, | ||
nullable: false | ||
} | ||
}, | ||
relations: { | ||
tags: { | ||
target: () => PostTag, | ||
type: "one-to-many", | ||
inverseSide: "post", | ||
cascade: true | ||
}, | ||
attachments: { | ||
target: () => PostAttachment, | ||
type: "one-to-many", | ||
inverseSide: "post", | ||
cascade: true | ||
} | ||
} | ||
}); |
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,35 @@ | ||
import { EntitySchema } from "../../../../src"; | ||
|
||
import Post from "./Post"; | ||
|
||
let id = 0; | ||
|
||
export default class PostAttachment { | ||
attachmentId: number; | ||
|
||
post: Post; | ||
|
||
constructor () { | ||
this.attachmentId = id++; | ||
} | ||
} | ||
|
||
export const PostAttachmentSchema = new EntitySchema<PostAttachment>({ | ||
name: "PostAttachment", | ||
target: PostAttachment, | ||
columns: { | ||
attachmentId: { | ||
type: Number, | ||
primary: true, | ||
nullable: false | ||
} | ||
}, | ||
relations: { | ||
post: { | ||
primary: true, | ||
nullable: false, | ||
target: () => Post, | ||
type: "many-to-one" | ||
} | ||
} | ||
}); |
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,51 @@ | ||
import { EntitySchema } from "../../../../src"; | ||
|
||
import Post from "./Post"; | ||
|
||
let id = 0; | ||
|
||
export default class PostTag { | ||
tagId: number; | ||
|
||
tagOtherId: string; | ||
|
||
tagPostId: string; | ||
|
||
post: Post; | ||
|
||
constructor () { | ||
this.tagId = id++; | ||
} | ||
} | ||
|
||
export const PostTagSchema = new EntitySchema<PostTag>({ | ||
name: "PostTag", | ||
target: PostTag, | ||
columns: { | ||
tagOtherId: { | ||
type: Number, | ||
primary: true | ||
}, | ||
tagPostId: { | ||
type: Number, | ||
primary: true | ||
}, | ||
tagId: { | ||
type: Number, | ||
primary: true, | ||
nullable: false | ||
} | ||
}, | ||
relations: { | ||
post: { | ||
primary: true, | ||
nullable: false, | ||
target: () => Post, | ||
type: "many-to-one", | ||
joinColumn: [ | ||
{ name: "tagPostId", referencedColumnName: "postId" }, | ||
{ name: "tagOtherId", referencedColumnName: "otherId" } | ||
] | ||
} | ||
} | ||
}); |
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,66 @@ | ||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; | ||
import {Connection} from "../../../src"; | ||
|
||
import { assert } from "chai"; | ||
|
||
import Post, { PostSchema } from "./entity/Post"; | ||
import PostTag, { PostTagSchema } from "./entity/PostTag"; | ||
import PostAttachment, { PostAttachmentSchema } from "./entity/PostAttachment"; | ||
|
||
describe("github issues > #6399 Combining ManyToOne, Cascade, & Composite Primary Key causes Unique Constraint issues", () => { | ||
|
||
let connections: Connection[]; | ||
before(async () => connections = await createTestingConnections({ | ||
entities: [PostSchema, PostTagSchema, PostAttachmentSchema], | ||
enabledDrivers: ["sqlite"], | ||
})); | ||
beforeEach(() => reloadTestingDatabases(connections)); | ||
after(() => closeTestingConnections(connections)); | ||
|
||
it("persisting the cascading entities should succeed", () => Promise.all(connections.map(async connection => { | ||
|
||
const post = new Post(); | ||
const postTag = new PostTag(); | ||
post.tags = [postTag]; | ||
|
||
await connection.manager.save(post, { reload: true }); | ||
|
||
try { | ||
await connection.manager.save(post); | ||
} catch (e) { | ||
assert.fail(e.toString(), null, "Second save had an exception"); | ||
} | ||
}))); | ||
|
||
it("persisting the cascading entities without JoinColumn should succeed", () => Promise.all(connections.map(async connection => { | ||
|
||
const post = new Post(); | ||
const postAttachment = new PostAttachment(); | ||
post.attachments = [postAttachment]; | ||
|
||
await connection.manager.save(post, { reload: true }); | ||
|
||
try { | ||
await connection.manager.save(post); | ||
} catch (e) { | ||
assert.fail(e.toString(), null, "Second save had an exception"); | ||
} | ||
}))); | ||
|
||
it("persisting the child entity should succeed", () => Promise.all(connections.map(async connection => { | ||
const post = new Post(); | ||
|
||
await connection.manager.save<Post>(post); | ||
|
||
const postTag = new PostTag(); | ||
postTag.post = post; | ||
|
||
await connection.manager.save(postTag, { reload: true }); | ||
|
||
try { | ||
await connection.manager.save(postTag); | ||
} catch (e) { | ||
assert.fail(e.toString(), null, "Second save had an exception"); | ||
} | ||
}))); | ||
}); |