mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
minor fixes;
working on RelationId tests;
This commit is contained in:
parent
f91537b48d
commit
cdae9fb31c
@ -382,7 +382,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
|
||||
// (example) here we seek a Details loaded from the database in the subjects
|
||||
// (example) here relatedSubject.databaseEntity is a Details
|
||||
// (example) and we need to compare details.id === post.detailsId
|
||||
return relation.entityMetadata.compareIds(relationIdInDatabaseEntity, relation.getEntityValue(relatedSubject.databaseEntity)); // relation.joinColumns[0].referencedColumn!.getEntityValue(relatedSubject.databaseEntity) === relationIdInDatabaseEntity;
|
||||
return relation.entityMetadata.compareIds(relationIdInDatabaseEntity, relation.getEntityValue(relatedSubject.databaseEntity));
|
||||
});
|
||||
|
||||
// if not loaded yet then load it from the database
|
||||
|
||||
@ -126,9 +126,12 @@ export class RelationIdLoader {
|
||||
if (mappedColumns.length === 0)
|
||||
return { relationIdAttribute: relationIdAttr, results: [] };
|
||||
|
||||
const joinColumnConditions = mappedColumns.map(mappedColumn => {
|
||||
const parameters: ObjectLiteral = {};
|
||||
const joinColumnConditions = mappedColumns.map((mappedColumn, index) => {
|
||||
return Object.keys(mappedColumn).map(key => {
|
||||
return junctionAlias + "." + key + " = " + mappedColumn[key];
|
||||
const parameterName = key + index;
|
||||
parameters[parameterName] = mappedColumn[key];
|
||||
return junctionAlias + "." + key + " = :" + parameterName;
|
||||
}).join(" AND ");
|
||||
});
|
||||
|
||||
@ -153,7 +156,8 @@ export class RelationIdLoader {
|
||||
});
|
||||
|
||||
qb.fromTable(inverseSideTableName, inverseSideTableAlias)
|
||||
.innerJoin(junctionTableName, junctionAlias, condition);
|
||||
.innerJoin(junctionTableName, junctionAlias, condition)
|
||||
.setParameters(parameters);
|
||||
|
||||
// apply condition (custom query builder factory)
|
||||
if (relationIdAttr.queryBuilderFactory)
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe.skip("benchmark > bulk-save", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
@ -18,11 +15,11 @@ describe.skip("benchmark > bulk-save", () => {
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
|
||||
it("testing bulk save of 100 objects", () => Promise.all(connections.map(async connection => {
|
||||
it("testing bulk save of 1000 objects", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const posts: Post[] = [];
|
||||
|
||||
for (let i = 1; i <= 100; i++) {
|
||||
for (let i = 1; i <= 1000; i++) {
|
||||
const post = new Post();
|
||||
post.title = `Post #${i}`;
|
||||
post.text = `Post #${i} text`;
|
||||
|
||||
@ -220,7 +220,7 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when RelationId decorator used on inherit relation", () => Promise.all(connections.map(async connection => {
|
||||
it("should load ids when RelationId decorator used on nested relation", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "photo1";
|
||||
@ -300,7 +300,7 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
})));
|
||||
|
||||
it("should not load ids of inherit relations when RelationId decorator used on inherit relation and parent relation was not found", () => Promise.all(connections.map(async connection => {
|
||||
it("should not load ids of nested relations when RelationId decorator used on inherit relation and parent relation was not found", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "photo1";
|
||||
@ -332,7 +332,7 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when RelationId decorator used on inherit relation with additional conditions", () => Promise.all(connections.map(async connection => {
|
||||
it("should load ids when RelationId decorator used on nested relation with additional conditions", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "photo1";
|
||||
|
||||
@ -6,7 +6,7 @@ import {expect} from "chai";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Subcounters} from "./entity/Subcounters";
|
||||
|
||||
describe("embedded > multiple-primary-columns-with-inherit-embed", () => {
|
||||
describe("embedded > multiple-primary-columns-with-nested-embed", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
@ -1,7 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Post} from "./entity/Post";
|
||||
@ -61,7 +61,7 @@ describe("query builder > load-relation-count-and-map > one-to-many", () => {
|
||||
expect(loadedPost!.categoryCount).to.be.equal(2);
|
||||
})));
|
||||
|
||||
it("should load relation count on inherit relations", () => Promise.all(connections.map(async connection => {
|
||||
it("should load relation count on nested relations", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "image #1";
|
||||
|
||||
@ -280,7 +280,7 @@ describe("query builder > relation-id > many-to-many > basic-functionality", ()
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on inherit relation", () => Promise.all(connections.map(async connection => {
|
||||
it("should load ids when loadRelationIdAndMap used on nested relation", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "photo1";
|
||||
@ -328,7 +328,7 @@ describe("query builder > relation-id > many-to-many > basic-functionality", ()
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on inherit relation with additional conditions", () => Promise.all(connections.map(async connection => {
|
||||
it("should load ids when loadRelationIdAndMap used on nested relation with additional conditions", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "photo1";
|
||||
@ -374,7 +374,7 @@ describe("query builder > relation-id > many-to-many > basic-functionality", ()
|
||||
|
||||
})));
|
||||
|
||||
it("should not load ids of inherit relations when loadRelationIdAndMap used on inherit relation and parent relation was not found", () => Promise.all(connections.map(async connection => {
|
||||
it("should not load ids of nested relations when loadRelationIdAndMap used on inherit relation and parent relation was not found", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "photo1";
|
||||
|
||||
@ -0,0 +1,328 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases
|
||||
} from "../../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Counters} from "./entity/Counters";
|
||||
import {User} from "./entity/User";
|
||||
import {Subcounters} from "./entity/Subcounters";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe("query builder > relation-id > many-to-many > embedded-with-multiple-pk", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchemaOnConnection: true,
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
describe("owner side", () => {
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on embedded table and each table have primary key", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const user1 = new User();
|
||||
user1.id = 1;
|
||||
user1.name = "Alice";
|
||||
await connection.manager.save(user1);
|
||||
|
||||
const user2 = new User();
|
||||
user2.id = 2;
|
||||
user2.name = "Bob";
|
||||
await connection.manager.save(user2);
|
||||
|
||||
const user3 = new User();
|
||||
user3.id = 3;
|
||||
user3.name = "Clara";
|
||||
await connection.manager.save(user3);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.name = "cars";
|
||||
await connection.manager.save(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.name = "BMW";
|
||||
await connection.manager.save(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.id = 3;
|
||||
category3.name = "airplanes";
|
||||
await connection.manager.save(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.id = 4;
|
||||
category4.name = "Boeing";
|
||||
await connection.manager.save(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.counters = new Counters();
|
||||
post1.counters.code = 111;
|
||||
post1.counters.likes = 1;
|
||||
post1.counters.comments = 2;
|
||||
post1.counters.favorites = 3;
|
||||
post1.counters.categories = [category1, category2];
|
||||
post1.counters.subcounters = new Subcounters();
|
||||
post1.counters.subcounters.version = 1;
|
||||
post1.counters.subcounters.watches = 2;
|
||||
post1.counters.subcounters.watchedUsers = [user1, user2];
|
||||
await connection.manager.save(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.title = "About Boeing";
|
||||
post2.counters = new Counters();
|
||||
post2.counters.code = 222;
|
||||
post2.counters.likes = 3;
|
||||
post2.counters.comments = 4;
|
||||
post2.counters.favorites = 5;
|
||||
post2.counters.categories = [category3, category4];
|
||||
post2.counters.subcounters = new Subcounters();
|
||||
post2.counters.subcounters.version = 1;
|
||||
post2.counters.subcounters.watches = 1;
|
||||
post2.counters.subcounters.watchedUsers = [user3];
|
||||
await connection.manager.save(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.counters.categoryIds", "post.counters.categories")
|
||||
.loadRelationIdAndMap("post.counters.subcounters.watchedUserIds", "post.counters.subcounters.watchedUsers")
|
||||
.orderBy("post.id")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
code: 111,
|
||||
likes: 1,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
categoryIds: [
|
||||
{ id: 1, name: "cars"},
|
||||
{ id: 2, name: "BMW"}
|
||||
],
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserIds: [
|
||||
{ id: 1, name: "Alice"},
|
||||
{ id: 2, name: "Bob"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About Boeing",
|
||||
counters: {
|
||||
code: 222,
|
||||
likes: 3,
|
||||
comments: 4,
|
||||
favorites: 5,
|
||||
categoryIds: [
|
||||
{ id: 3, name: "airplanes"},
|
||||
{ id: 4, name: "Boeing"}
|
||||
],
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 1,
|
||||
watchedUserIds: [
|
||||
{ id: 3, name: "Clara"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.counters.categoryIds", "post.counters.categories")
|
||||
.loadRelationIdAndMap("post.counters.subcounters.watchedUserIds", "post.counters.subcounters.watchedUsers")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.andWhere("post.counters.code = :code", { code: 111 })
|
||||
.andWhere("post.counters.subcounters.version = :version", { version: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
code: 111,
|
||||
likes: 1,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
categoryIds: [
|
||||
{ id: 1, name: "cars"},
|
||||
{ id: 2, name: "BMW"}
|
||||
],
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserIds: [
|
||||
{ id: 1, name: "Alice"},
|
||||
{ id: 2, name: "Bob"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
})));
|
||||
});
|
||||
|
||||
describe("inverse side", () => {
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on embedded table and each table have primary key", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.counters = new Counters();
|
||||
post1.counters.code = 111;
|
||||
post1.counters.likes = 1;
|
||||
post1.counters.comments = 2;
|
||||
post1.counters.favorites = 3;
|
||||
post1.counters.subcounters = new Subcounters();
|
||||
post1.counters.subcounters.version = 1;
|
||||
post1.counters.subcounters.watches = 2;
|
||||
await connection.manager.save(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.title = "About Audi";
|
||||
post2.counters = new Counters();
|
||||
post2.counters.code = 222;
|
||||
post2.counters.likes = 3;
|
||||
post2.counters.comments = 4;
|
||||
post2.counters.favorites = 5;
|
||||
post2.counters.subcounters = new Subcounters();
|
||||
post2.counters.subcounters.version = 1;
|
||||
post2.counters.subcounters.watches = 5;
|
||||
await connection.manager.save(post2);
|
||||
|
||||
const post3 = new Post();
|
||||
post3.id = 3;
|
||||
post3.title = "About Boeing";
|
||||
post3.counters = new Counters();
|
||||
post3.counters.code = 333;
|
||||
post3.counters.likes = 6;
|
||||
post3.counters.comments = 7;
|
||||
post3.counters.favorites = 8;
|
||||
post3.counters.subcounters = new Subcounters();
|
||||
post3.counters.subcounters.version = 2;
|
||||
post3.counters.subcounters.watches = 10;
|
||||
await connection.manager.save(post3);
|
||||
|
||||
const post4 = new Post();
|
||||
post4.id = 4;
|
||||
post4.title = "About Airbus";
|
||||
post4.counters = new Counters();
|
||||
post4.counters.code = 444;
|
||||
post4.counters.likes = 9;
|
||||
post4.counters.comments = 10;
|
||||
post4.counters.favorites = 11;
|
||||
post4.counters.subcounters = new Subcounters();
|
||||
post4.counters.subcounters.version = 3;
|
||||
post4.counters.subcounters.watches = 10;
|
||||
await connection.manager.save(post4);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.name = "cars";
|
||||
category1.posts = [post1, post2];
|
||||
await connection.manager.save(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.name = "airplanes";
|
||||
category2.posts = [post3, post4];
|
||||
await connection.manager.save(category2);
|
||||
|
||||
const user1 = new User();
|
||||
user1.id = 1;
|
||||
user1.name = "Alice";
|
||||
user1.posts = [post1, post2];
|
||||
await connection.manager.save(user1);
|
||||
|
||||
const user2 = new User();
|
||||
user2.id = 2;
|
||||
user2.name = "Bob";
|
||||
user2.posts = [post3, post4];
|
||||
await connection.manager.save(user2);
|
||||
|
||||
const loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
.orderBy("category.id")
|
||||
.getMany();
|
||||
|
||||
expect(loadedCategories[0].postIds).to.not.be.empty;
|
||||
expect(loadedCategories[0].postIds.length).to.be.equal(2);
|
||||
expect(loadedCategories[0].postIds[0]).to.be.eql({ id: 1, counters: { code: 111, subcounters: { version: 1 }} });
|
||||
expect(loadedCategories[0].postIds[1]).to.be.eql({ id: 2, counters: { code: 222, subcounters: { version: 1 }} });
|
||||
expect(loadedCategories[1].postIds).to.not.be.empty;
|
||||
expect(loadedCategories[1].postIds.length).to.be.equal(2);
|
||||
expect(loadedCategories[1].postIds[0]).to.be.eql({ id: 3, counters: { code: 333, subcounters: { version: 2 }} });
|
||||
expect(loadedCategories[1].postIds[1]).to.be.eql({ id: 4, counters: { code: 444, subcounters: { version: 3 }} });
|
||||
|
||||
const loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
.where("category.id = :id", { id: 1 })
|
||||
.andWhere("category.name = :name", { name: "cars" })
|
||||
.getOne();
|
||||
|
||||
expect(loadedCategory!.postIds).to.not.be.empty;
|
||||
expect(loadedCategory!.postIds.length).to.be.equal(2);
|
||||
expect(loadedCategory!.postIds[0]).to.be.eql({ id: 1, counters: { code: 111, subcounters: { version: 1 }} });
|
||||
expect(loadedCategory!.postIds[1]).to.be.eql({ id: 2, counters: { code: 222, subcounters: { version: 1 }} });
|
||||
|
||||
const loadedUsers = await connection.manager
|
||||
.createQueryBuilder(User, "user")
|
||||
.loadRelationIdAndMap("user.postIds", "user.posts")
|
||||
.orderBy("user.id")
|
||||
.getMany();
|
||||
|
||||
expect(loadedUsers[0].postIds).to.not.be.empty;
|
||||
expect(loadedUsers[0].postIds.length).to.be.equal(2);
|
||||
expect(loadedUsers[0].postIds[0]).to.be.eql({ id: 1, counters: { code: 111, subcounters: { version: 1 }} });
|
||||
expect(loadedUsers[0].postIds[1]).to.be.eql({ id: 2, counters: { code: 222, subcounters: { version: 1 }} });
|
||||
expect(loadedUsers[1].postIds).to.not.be.empty;
|
||||
expect(loadedUsers[1].postIds.length).to.be.equal(2);
|
||||
expect(loadedUsers[1].postIds[0]).to.be.eql({ id: 3, counters: { code: 333, subcounters: { version: 2 }} });
|
||||
expect(loadedUsers[1].postIds[1]).to.be.eql({ id: 4, counters: { code: 444, subcounters: { version: 3 }} });
|
||||
|
||||
const loadedUser = await connection.manager
|
||||
.createQueryBuilder(User, "user")
|
||||
.loadRelationIdAndMap("user.postIds", "user.posts")
|
||||
.where("user.id = :id", { id: 1 })
|
||||
.andWhere("user.name = :name", { name: "Alice" })
|
||||
.getOne();
|
||||
|
||||
expect(loadedUser!.postIds).to.not.be.empty;
|
||||
expect(loadedUser!.postIds.length).to.be.equal(2);
|
||||
expect(loadedUser!.postIds[0]).to.be.eql({ id: 1, counters: { code: 111, subcounters: { version: 1 }} });
|
||||
expect(loadedUser!.postIds[1]).to.be.eql({ id: 2, counters: { code: 222, subcounters: { version: 1 }} });
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@ -0,0 +1,22 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Post} from "./Post";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "name"])
|
||||
export class Category {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
name: string;
|
||||
|
||||
@ManyToMany(type => Post, post => post.counters.categories)
|
||||
posts: Post[];
|
||||
|
||||
postIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Category} from "./Category";
|
||||
import {Subcounters} from "./Subcounters";
|
||||
|
||||
export class Counters {
|
||||
|
||||
@PrimaryColumn()
|
||||
code: number;
|
||||
|
||||
@Column()
|
||||
likes: number;
|
||||
|
||||
@Column()
|
||||
comments: number;
|
||||
|
||||
@Column()
|
||||
favorites: number;
|
||||
|
||||
@ManyToMany(type => Category, category => category.posts)
|
||||
@JoinTable()
|
||||
categories: Category[];
|
||||
|
||||
@Embedded(() => Subcounters)
|
||||
subcounters: Subcounters;
|
||||
|
||||
categoryIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {Counters} from "./Counters";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "counters.code", "counters.subcounters.version"], { unique: true })
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Embedded(() => Counters)
|
||||
counters: Counters;
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {User} from "./User";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@PrimaryColumn()
|
||||
version: number;
|
||||
|
||||
@Column()
|
||||
watches: number;
|
||||
|
||||
@ManyToMany(type => User, user => user.posts)
|
||||
@JoinTable()
|
||||
watchedUsers: User[];
|
||||
|
||||
watchedUserIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "name"])
|
||||
export class User {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
name: string;
|
||||
|
||||
@ManyToMany(type => Post, post => post.counters.subcounters.watchedUsers)
|
||||
posts: Post[];
|
||||
|
||||
postIds: number[];
|
||||
|
||||
}
|
||||
@ -91,7 +91,6 @@ describe("query builder > relation-id > many-to-many > embedded", () => {
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
likes: 1,
|
||||
@ -99,6 +98,7 @@ describe("query builder > relation-id > many-to-many > embedded", () => {
|
||||
favorites: 3,
|
||||
categoryIds: [1, 2],
|
||||
subcounters: {
|
||||
id: 1,
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserIds: [1, 2]
|
||||
@ -108,7 +108,6 @@ describe("query builder > relation-id > many-to-many > embedded", () => {
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About Boeing",
|
||||
counters: {
|
||||
likes: 3,
|
||||
@ -116,6 +115,7 @@ describe("query builder > relation-id > many-to-many > embedded", () => {
|
||||
favorites: 5,
|
||||
categoryIds: [3, 4],
|
||||
subcounters: {
|
||||
id: 2,
|
||||
version: 1,
|
||||
watches: 1,
|
||||
watchedUserIds: [3]
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {Counters} from "./Counters";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {User} from "./User";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {User} from "./User";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
version: number;
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ describe("query builder > relation-id > many-to-many > multiple-pk", () => {
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when only one entity have multiple primary keys", () => Promise.all(connections.map(async connection => {
|
||||
it("should load ids when only one entity have multiple primary key", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "Image #1";
|
||||
@ -472,7 +472,7 @@ describe("query builder > relation-id > many-to-many > multiple-pk", () => {
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when only one entity have multiple primary keys", () => Promise.all(connections.map(async connection => {
|
||||
it("should load ids when only one entity have multiple primary key", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
|
||||
@ -110,7 +110,7 @@ describe("query builder > relation-id > many-to-one > basic-functionality", () =
|
||||
expect(loadedPostCategory!.postId).to.be.equal(1);
|
||||
})));
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on inherit relation and target entity has multiple primary keys", () => Promise.all(connections.map(async connection => {
|
||||
it("should load ids when loadRelationIdAndMap used on nested relation and target entity has multiple primary keys", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
|
||||
@ -0,0 +1,155 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases
|
||||
} from "../../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Counters} from "./entity/Counters";
|
||||
import {User} from "./entity/User";
|
||||
import {Subcounters} from "./entity/Subcounters";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe("query builder > relation-id > many-to-one > embedded-with-multiple-pk", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchemaOnConnection: true,
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on embedded table and each table have primary key", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const user1 = new User();
|
||||
user1.id = 1;
|
||||
user1.name = "Alice";
|
||||
await connection.manager.save(user1);
|
||||
|
||||
const user2 = new User();
|
||||
user2.id = 2;
|
||||
user2.name = "Bob";
|
||||
await connection.manager.save(user2);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.name = "cars";
|
||||
await connection.manager.save(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.name = "airplanes";
|
||||
await connection.manager.save(category2);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.counters = new Counters();
|
||||
post1.counters.code = 111;
|
||||
post1.counters.likes = 1;
|
||||
post1.counters.comments = 2;
|
||||
post1.counters.favorites = 3;
|
||||
post1.counters.category = category1;
|
||||
post1.counters.subcounters = new Subcounters();
|
||||
post1.counters.subcounters.version = 1;
|
||||
post1.counters.subcounters.watches = 2;
|
||||
post1.counters.subcounters.watchedUser = user1;
|
||||
await connection.manager.save(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.title = "About Boeing";
|
||||
post2.counters = new Counters();
|
||||
post2.counters.code = 222;
|
||||
post2.counters.likes = 3;
|
||||
post2.counters.comments = 4;
|
||||
post2.counters.favorites = 5;
|
||||
post2.counters.category = category2;
|
||||
post2.counters.subcounters = new Subcounters();
|
||||
post2.counters.subcounters.version = 1;
|
||||
post2.counters.subcounters.watches = 1;
|
||||
post2.counters.subcounters.watchedUser = user2;
|
||||
await connection.manager.save(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.counters.categoryId", "post.counters.category")
|
||||
.loadRelationIdAndMap("post.counters.subcounters.watchedUserId", "post.counters.subcounters.watchedUser")
|
||||
.orderBy("post.id")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
code: 111,
|
||||
likes: 1,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
categoryId: { id: 1, name: "cars"},
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserId: { id: 1, name: "Alice"}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About Boeing",
|
||||
counters: {
|
||||
code: 222,
|
||||
likes: 3,
|
||||
comments: 4,
|
||||
favorites: 5,
|
||||
categoryId: { id: 2, name: "airplanes"},
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 1,
|
||||
watchedUserId: { id: 2, name: "Bob"}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.counters.categoryId", "post.counters.category")
|
||||
.loadRelationIdAndMap("post.counters.subcounters.watchedUserId", "post.counters.subcounters.watchedUser")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.andWhere("post.counters.code = :code", { code: 111 })
|
||||
.andWhere("post.counters.subcounters.version = :version", { version: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
code: 111,
|
||||
likes: 1,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
categoryId: { id: 1, name: "cars"},
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserId: { id: 1, name: "Alice"}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -0,0 +1,15 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "name"])
|
||||
export class Category {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
name: string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
import {Category} from "./Category";
|
||||
import {Subcounters} from "./Subcounters";
|
||||
|
||||
export class Counters {
|
||||
|
||||
@PrimaryColumn()
|
||||
code: number;
|
||||
|
||||
@Column()
|
||||
likes: number;
|
||||
|
||||
@Column()
|
||||
comments: number;
|
||||
|
||||
@Column()
|
||||
favorites: number;
|
||||
|
||||
@ManyToOne(type => Category)
|
||||
category: Category;
|
||||
|
||||
@Embedded(() => Subcounters)
|
||||
subcounters: Subcounters;
|
||||
|
||||
categoryId: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {Counters} from "./Counters";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "counters.code", "counters.subcounters.version"], { unique: true })
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Embedded(() => Counters)
|
||||
counters: Counters;
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {User} from "./User";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@PrimaryColumn()
|
||||
version: number;
|
||||
|
||||
@Column()
|
||||
watches: number;
|
||||
|
||||
@ManyToOne(type => User)
|
||||
watchedUser: User;
|
||||
|
||||
watchedUserId: number;
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "name"])
|
||||
export class User {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
name: string;
|
||||
|
||||
}
|
||||
@ -79,7 +79,6 @@ describe("query builder > relation-id > many-to-one > embedded", () => {
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
likes: 1,
|
||||
@ -87,6 +86,7 @@ describe("query builder > relation-id > many-to-one > embedded", () => {
|
||||
favorites: 3,
|
||||
categoryId: 1,
|
||||
subcounters: {
|
||||
id: 1,
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserId: 1
|
||||
@ -96,7 +96,6 @@ describe("query builder > relation-id > many-to-one > embedded", () => {
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About Boeing",
|
||||
counters: {
|
||||
likes: 3,
|
||||
@ -104,6 +103,7 @@ describe("query builder > relation-id > many-to-one > embedded", () => {
|
||||
favorites: 5,
|
||||
categoryId: 2,
|
||||
subcounters: {
|
||||
id: 2,
|
||||
version: 1,
|
||||
watches: 1,
|
||||
watchedUserId: 2
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
import {Category} from "./Category";
|
||||
@ -17,7 +16,6 @@ export class Counters {
|
||||
favorites: number;
|
||||
|
||||
@ManyToOne(type => Category, category => category.posts)
|
||||
@JoinTable()
|
||||
category: Category;
|
||||
|
||||
@Embedded(() => Subcounters)
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {Counters} from "./Counters";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {User} from "./User";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
version: number;
|
||||
|
||||
|
||||
@ -0,0 +1,187 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases
|
||||
} from "../../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Counters} from "./entity/Counters";
|
||||
import {User} from "./entity/User";
|
||||
import {Subcounters} from "./entity/Subcounters";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe("query builder > relation-id > one-to-many > embedded-with-multiple-pk", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchemaOnConnection: true,
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on embedded table and each table have primary key", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const user1 = new User();
|
||||
user1.id = 1;
|
||||
user1.name = "Alice";
|
||||
await connection.manager.save(user1);
|
||||
|
||||
const user2 = new User();
|
||||
user2.id = 2;
|
||||
user2.name = "Bob";
|
||||
await connection.manager.save(user2);
|
||||
|
||||
const user3 = new User();
|
||||
user3.id = 3;
|
||||
user3.name = "Clara";
|
||||
await connection.manager.save(user3);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.name = "cars";
|
||||
await connection.manager.save(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.name = "BMW";
|
||||
await connection.manager.save(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.id = 3;
|
||||
category3.name = "airplanes";
|
||||
await connection.manager.save(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.id = 4;
|
||||
category4.name = "Boeing";
|
||||
await connection.manager.save(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.counters = new Counters();
|
||||
post1.counters.code = 111;
|
||||
post1.counters.likes = 1;
|
||||
post1.counters.comments = 2;
|
||||
post1.counters.favorites = 3;
|
||||
post1.counters.categories = [category1, category2];
|
||||
post1.counters.subcounters = new Subcounters();
|
||||
post1.counters.subcounters.version = 1;
|
||||
post1.counters.subcounters.watches = 2;
|
||||
post1.counters.subcounters.watchedUsers = [user1, user2];
|
||||
await connection.manager.save(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.title = "About Boeing";
|
||||
post2.counters = new Counters();
|
||||
post2.counters.code = 222;
|
||||
post2.counters.likes = 3;
|
||||
post2.counters.comments = 4;
|
||||
post2.counters.favorites = 5;
|
||||
post2.counters.categories = [category3, category4];
|
||||
post2.counters.subcounters = new Subcounters();
|
||||
post2.counters.subcounters.version = 1;
|
||||
post2.counters.subcounters.watches = 1;
|
||||
post2.counters.subcounters.watchedUsers = [user3];
|
||||
await connection.manager.save(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.counters.categoryIds", "post.counters.categories")
|
||||
.loadRelationIdAndMap("post.counters.subcounters.watchedUserIds", "post.counters.subcounters.watchedUsers")
|
||||
.orderBy("post.id")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
code: 111,
|
||||
likes: 1,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
categoryIds: [
|
||||
{ id: 1, name: "cars"},
|
||||
{ id: 2, name: "BMW"}
|
||||
],
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserIds: [
|
||||
{ id: 1, name: "Alice"},
|
||||
{ id: 2, name: "Bob"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About Boeing",
|
||||
counters: {
|
||||
code: 222,
|
||||
likes: 3,
|
||||
comments: 4,
|
||||
favorites: 5,
|
||||
categoryIds: [
|
||||
{ id: 3, name: "airplanes"},
|
||||
{ id: 4, name: "Boeing"}
|
||||
],
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 1,
|
||||
watchedUserIds: [
|
||||
{ id: 3, name: "Clara"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.counters.categoryIds", "post.counters.categories")
|
||||
.loadRelationIdAndMap("post.counters.subcounters.watchedUserIds", "post.counters.subcounters.watchedUsers")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.andWhere("post.counters.code = :code", { code: 111 })
|
||||
.andWhere("post.counters.subcounters.version = :version", { version: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
code: 111,
|
||||
likes: 1,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
categoryIds: [
|
||||
{ id: 1, name: "cars"},
|
||||
{ id: 2, name: "BMW"}
|
||||
],
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserIds: [
|
||||
{ id: 1, name: "Alice"},
|
||||
{ id: 2, name: "Bob"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -0,0 +1,20 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {Post} from "./Post";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "name"])
|
||||
export class Category {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
name: string;
|
||||
|
||||
@ManyToOne(type => Post, post => post.counters.categories)
|
||||
post: Post;
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {OneToMany} from "../../../../../../../src/decorator/relations/OneToMany";
|
||||
import {Category} from "./Category";
|
||||
import {Subcounters} from "./Subcounters";
|
||||
|
||||
export class Counters {
|
||||
|
||||
@PrimaryColumn()
|
||||
code: number;
|
||||
|
||||
@Column()
|
||||
likes: number;
|
||||
|
||||
@Column()
|
||||
comments: number;
|
||||
|
||||
@Column()
|
||||
favorites: number;
|
||||
|
||||
@OneToMany(type => Category, category => category.post)
|
||||
categories: Category[];
|
||||
|
||||
@Embedded(() => Subcounters)
|
||||
subcounters: Subcounters;
|
||||
|
||||
categoryIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {Counters} from "./Counters";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "counters.code", "counters.subcounters.version"], { unique: true })
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Embedded(() => Counters)
|
||||
counters: Counters;
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {OneToMany} from "../../../../../../../src/decorator/relations/OneToMany";
|
||||
import {User} from "./User";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@PrimaryColumn()
|
||||
version: number;
|
||||
|
||||
@Column()
|
||||
watches: number;
|
||||
|
||||
@OneToMany(type => User, user => user.post)
|
||||
watchedUsers: User[];
|
||||
|
||||
watchedUserIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "name"])
|
||||
export class User {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
name: string;
|
||||
|
||||
@ManyToOne(type => Post, post => post.counters.subcounters.watchedUsers)
|
||||
post: Post;
|
||||
|
||||
}
|
||||
@ -91,7 +91,6 @@ describe("query builder > relation-id > many-to-many > embedded", () => {
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
likes: 1,
|
||||
@ -99,6 +98,7 @@ describe("query builder > relation-id > many-to-many > embedded", () => {
|
||||
favorites: 3,
|
||||
categoryIds: [1, 2],
|
||||
subcounters: {
|
||||
id: 1,
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserIds: [1, 2]
|
||||
@ -108,7 +108,6 @@ describe("query builder > relation-id > many-to-many > embedded", () => {
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About Boeing",
|
||||
counters: {
|
||||
likes: 3,
|
||||
@ -116,6 +115,7 @@ describe("query builder > relation-id > many-to-many > embedded", () => {
|
||||
favorites: 5,
|
||||
categoryIds: [3, 4],
|
||||
subcounters: {
|
||||
id: 2,
|
||||
version: 1,
|
||||
watches: 1,
|
||||
watchedUserIds: [3]
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {Counters} from "./Counters";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {OneToMany} from "../../../../../../../src/decorator/relations/OneToMany";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {User} from "./User";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
version: number;
|
||||
|
||||
|
||||
@ -0,0 +1,155 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases
|
||||
} from "../../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Counters} from "./entity/Counters";
|
||||
import {User} from "./entity/User";
|
||||
import {Subcounters} from "./entity/Subcounters";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe("query builder > relation-id > one-to-one > embedded-with-multiple-pk", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchemaOnConnection: true,
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on embedded table and each table have primary key", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const user1 = new User();
|
||||
user1.id = 1;
|
||||
user1.name = "Alice";
|
||||
await connection.manager.save(user1);
|
||||
|
||||
const user2 = new User();
|
||||
user2.id = 2;
|
||||
user2.name = "Bob";
|
||||
await connection.manager.save(user2);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.name = "cars";
|
||||
await connection.manager.save(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.name = "airplanes";
|
||||
await connection.manager.save(category2);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.counters = new Counters();
|
||||
post1.counters.code = 111;
|
||||
post1.counters.likes = 1;
|
||||
post1.counters.comments = 2;
|
||||
post1.counters.favorites = 3;
|
||||
post1.counters.category = category1;
|
||||
post1.counters.subcounters = new Subcounters();
|
||||
post1.counters.subcounters.version = 1;
|
||||
post1.counters.subcounters.watches = 2;
|
||||
post1.counters.subcounters.watchedUser = user1;
|
||||
await connection.manager.save(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.title = "About Boeing";
|
||||
post2.counters = new Counters();
|
||||
post2.counters.code = 222;
|
||||
post2.counters.likes = 3;
|
||||
post2.counters.comments = 4;
|
||||
post2.counters.favorites = 5;
|
||||
post2.counters.category = category2;
|
||||
post2.counters.subcounters = new Subcounters();
|
||||
post2.counters.subcounters.version = 1;
|
||||
post2.counters.subcounters.watches = 1;
|
||||
post2.counters.subcounters.watchedUser = user2;
|
||||
await connection.manager.save(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.counters.categoryId", "post.counters.category")
|
||||
.loadRelationIdAndMap("post.counters.subcounters.watchedUserId", "post.counters.subcounters.watchedUser")
|
||||
.orderBy("post.id")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
code: 111,
|
||||
likes: 1,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
categoryId: { id: 1, name: "cars"},
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserId: { id: 1, name: "Alice"}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About Boeing",
|
||||
counters: {
|
||||
code: 222,
|
||||
likes: 3,
|
||||
comments: 4,
|
||||
favorites: 5,
|
||||
categoryId: { id: 2, name: "airplanes"},
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 1,
|
||||
watchedUserId: { id: 2, name: "Bob"}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.counters.categoryId", "post.counters.category")
|
||||
.loadRelationIdAndMap("post.counters.subcounters.watchedUserId", "post.counters.subcounters.watchedUser")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.andWhere("post.counters.code = :code", { code: 111 })
|
||||
.andWhere("post.counters.subcounters.version = :version", { version: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
code: 111,
|
||||
likes: 1,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
categoryId: { id: 1, name: "cars"},
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserId: { id: 1, name: "Alice"}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -0,0 +1,15 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "name"])
|
||||
export class Category {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
name: string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {OneToOne} from "../../../../../../../src/decorator/relations/OneToOne";
|
||||
import {JoinColumn} from "../../../../../../../src/decorator/relations/JoinColumn";
|
||||
import {Category} from "./Category";
|
||||
import {Subcounters} from "./Subcounters";
|
||||
|
||||
export class Counters {
|
||||
|
||||
@PrimaryColumn()
|
||||
code: number;
|
||||
|
||||
@Column()
|
||||
likes: number;
|
||||
|
||||
@Column()
|
||||
comments: number;
|
||||
|
||||
@Column()
|
||||
favorites: number;
|
||||
|
||||
@OneToOne(type => Category)
|
||||
@JoinColumn()
|
||||
category: Category;
|
||||
|
||||
@Embedded(() => Subcounters)
|
||||
subcounters: Subcounters;
|
||||
|
||||
categoryId: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {Counters} from "./Counters";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "counters.code", "counters.subcounters.version"], { unique: true })
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Embedded(() => Counters)
|
||||
counters: Counters;
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {OneToOne} from "../../../../../../../src/decorator/relations/OneToOne";
|
||||
import {JoinColumn} from "../../../../../../../src/decorator/relations/JoinColumn";
|
||||
import {User} from "./User";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@PrimaryColumn()
|
||||
version: number;
|
||||
|
||||
@Column()
|
||||
watches: number;
|
||||
|
||||
@OneToOne(type => User)
|
||||
@JoinColumn()
|
||||
watchedUser: User;
|
||||
|
||||
watchedUserId: number;
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "name"])
|
||||
export class User {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
name: string;
|
||||
|
||||
}
|
||||
@ -79,7 +79,6 @@ describe("query builder > relation-id > one-to-one > embedded", () => {
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
likes: 1,
|
||||
@ -87,6 +86,7 @@ describe("query builder > relation-id > one-to-one > embedded", () => {
|
||||
favorites: 3,
|
||||
categoryId: 1,
|
||||
subcounters: {
|
||||
id: 1,
|
||||
version: 1,
|
||||
watches: 2,
|
||||
watchedUserId: 1
|
||||
@ -96,7 +96,6 @@ describe("query builder > relation-id > one-to-one > embedded", () => {
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About Boeing",
|
||||
counters: {
|
||||
likes: 3,
|
||||
@ -104,6 +103,7 @@ describe("query builder > relation-id > one-to-one > embedded", () => {
|
||||
favorites: 5,
|
||||
categoryId: 2,
|
||||
subcounters: {
|
||||
id: 2,
|
||||
version: 1,
|
||||
watches: 1,
|
||||
watchedUserId: 2
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {Counters} from "./Counters";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {User} from "./User";
|
||||
import {OneToOne} from "../../../../../../../src/decorator/relations/OneToOne";
|
||||
import {JoinColumn} from "../../../../../../../src/decorator/relations/JoinColumn";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {User} from "./User";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
version: number;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user