mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
removed class table inheritance support
This commit is contained in:
parent
a15dbfb7c2
commit
2a0ae48dac
@ -18,7 +18,6 @@ feel free to ask us and community.
|
||||
* now you can disable persistence on any relation by setting `@OneToMany(type => Post, post => tag, { persistence: false })`. This can dramatically improve entity save performance.
|
||||
* `loadAllRelationIds` method of `QueryBuilder` now accepts list of relation paths that needs to be loaded, also `disableMixedMap` option is now by default set to false, but you can enable it via new method parameter `options`
|
||||
* lot of changes affect closure table pattern which is planned for fix in 0.3.0
|
||||
* lot of changes affect table inheritance patterns which are planned for fix in 0.3.0
|
||||
* now `returning` and `output` statements of `InsertQueryBuilder` support array of columns as argument
|
||||
* now when many-to-many and one-to-many relation set to `null` all items from that relation are removed, just like it would be set to empty array
|
||||
* fixed issues with relation updation from one-to-one non-owner side
|
||||
@ -46,6 +45,12 @@ Use `findOne(id)` method instead now.
|
||||
* added ability to disable listeners and subscribers in `save` and `remove` operations
|
||||
* added ability to save and remove objects in chunks
|
||||
* added ability to disable entity reloading after insertion and updation
|
||||
* class table inheritance functionality has been completely dropped
|
||||
* single table inheritance functionality has been fixed
|
||||
* `@SingleEntityChild` has been renamed to `@ChildEntity`
|
||||
* `@DiscriminatorValue` has been removed, instead parameter in `@ChildEntity` must be used, e.g. `@ChildEntity("value")`
|
||||
* `@DiscriminatorColumn` decorator has been removed, use `@TableInheritance` options instead now
|
||||
|
||||
|
||||
## 0.1.7
|
||||
|
||||
|
||||
@ -31,7 +31,6 @@ npm i typeorm@next
|
||||
- [ ] implement soft deletion
|
||||
- [ ] research ability to create one-to-many relations without inverse sides
|
||||
- [ ] research ability to create a single relation with multiple entities at once
|
||||
- [ ] fix all table-inheritance issues, better class-table and single-table inheritance support
|
||||
- [ ] add more tree-table features: nested set and materialized path; more repository methods
|
||||
- [ ] cli: create database backup command
|
||||
- [ ] extend `query` method functionality
|
||||
@ -50,3 +49,4 @@ npm i typeorm@next
|
||||
- [x] fix all issues with cascades and make stable functionality
|
||||
- [ ] implement API for manual migration creation
|
||||
- [x] add sql.js driver
|
||||
- [x] fix inheritance support issues
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../src/decorator/columns/Column";
|
||||
import {Person} from "./Person";
|
||||
import {SingleEntityChild} from "../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../src/decorator/entity/ChildEntity";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Employee extends Person {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import {Column} from "../../../src/decorator/columns/Column";
|
||||
import {Person} from "./Person";
|
||||
import {DiscriminatorValue} from "../../../src/decorator/DiscriminatorValue";
|
||||
import {SingleEntityChild} from "../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../src/decorator/entity/ChildEntity";
|
||||
|
||||
@SingleEntityChild()
|
||||
@DiscriminatorValue("home-sitter") // can be omitted
|
||||
@ChildEntity("home-sitter")
|
||||
export class Homesitter extends Person {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import {Column} from "../../../src/decorator/columns/Column";
|
||||
import {TableInheritance} from "../../../src/decorator/entity/TableInheritance";
|
||||
import {DiscriminatorColumn} from "../../../src/decorator/columns/DiscriminatorColumn";
|
||||
import {Entity} from "../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../src/decorator/columns/PrimaryColumn";
|
||||
|
||||
@ -8,8 +7,7 @@ import {PrimaryColumn} from "../../../src/decorator/columns/PrimaryColumn";
|
||||
// * check how it works when is join (conditions are not added in the joins right now)
|
||||
|
||||
@Entity("sample28_person")
|
||||
@TableInheritance("single-table")
|
||||
@DiscriminatorColumn({ name: "type", type: "varchar" })
|
||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||
export abstract class Person {
|
||||
|
||||
@PrimaryColumn("int")
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../src/decorator/columns/Column";
|
||||
import {Person} from "./Person";
|
||||
import {SingleEntityChild} from "../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../src/decorator/entity/ChildEntity";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Student extends Person {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,108 +0,0 @@
|
||||
import "reflect-metadata";
|
||||
import {ConnectionOptions, createConnection} from "../../src/index";
|
||||
import {Employee} from "./entity/Employee";
|
||||
import {Homesitter} from "./entity/Homesitter";
|
||||
import {Student} from "./entity/Student";
|
||||
import {Person} from "./entity/Person";
|
||||
|
||||
const options: ConnectionOptions = {
|
||||
type: "mysql",
|
||||
host: "localhost",
|
||||
port: 3306,
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: ["query", "error"],
|
||||
synchronize: true,
|
||||
entities: [
|
||||
Person,
|
||||
Employee,
|
||||
Homesitter,
|
||||
Student
|
||||
]
|
||||
};
|
||||
|
||||
createConnection(options).then(async connection => {
|
||||
|
||||
let employeeRepository = connection.getRepository(Employee);
|
||||
const employee = new Employee();
|
||||
employee.id = 1;
|
||||
employee.firstName = "umed";
|
||||
employee.lastName = "khudoiberdiev";
|
||||
employee.salary = 300000;
|
||||
|
||||
console.log("saving the employee: ");
|
||||
await employeeRepository.save(employee);
|
||||
console.log("employee has been saved: ", employee);
|
||||
|
||||
console.log("updating the employee: ");
|
||||
employee.firstName = "zuma";
|
||||
employee.lastName += "a";
|
||||
await employeeRepository.save(employee);
|
||||
console.log("employee has been updated: ", employee);
|
||||
|
||||
console.log("now loading the employee: ");
|
||||
const loadedEmployee = (await employeeRepository.findOne(1))!;
|
||||
console.log("loaded employee: ", loadedEmployee);
|
||||
|
||||
loadedEmployee.firstName = "dima";
|
||||
await employeeRepository.save(loadedEmployee);
|
||||
|
||||
const allEmployees = await employeeRepository.findAndCount();
|
||||
console.log("all employees: ", allEmployees);
|
||||
|
||||
console.log("deleting employee: ", loadedEmployee);
|
||||
await employeeRepository.remove(loadedEmployee);
|
||||
console.log("employee deleted");
|
||||
|
||||
console.log("-----------------");
|
||||
|
||||
/*let homesitterRepository = connection.getRepository(Homesitter);
|
||||
const homesitter = new Homesitter();
|
||||
homesitter.id = 2;
|
||||
homesitter.firstName = "umed";
|
||||
homesitter.lastName = "khudoiberdiev";
|
||||
homesitter.numberOfKids = 5;
|
||||
|
||||
console.log("saving the homesitter: ");
|
||||
await homesitterRepository.save(homesitter);
|
||||
console.log("homesitter has been saved: ", homesitter);
|
||||
|
||||
console.log("now loading the homesitter: ");
|
||||
const loadedHomesitter = await homesitterRepository.findOne(2);
|
||||
console.log("loaded homesitter: ", loadedHomesitter);
|
||||
|
||||
console.log("-----------------");
|
||||
|
||||
let studentRepository = connection.getRepository(Student);
|
||||
const student = new Student();
|
||||
student.id = 3;
|
||||
student.firstName = "umed";
|
||||
student.lastName = "khudoiberdiev";
|
||||
student.faculty = "computer science";
|
||||
|
||||
console.log("saving the student: ");
|
||||
await studentRepository.save(student);
|
||||
console.log("student has been saved: ", student);
|
||||
|
||||
console.log("now loading the student: ");
|
||||
const loadedStudent = await studentRepository.findOne(3);
|
||||
console.log("loaded student: ", loadedStudent);
|
||||
|
||||
console.log("-----------------");
|
||||
const secondEmployee = await employeeRepository.findOne(2);
|
||||
console.log("Non exist employee: ", secondEmployee);
|
||||
const thirdEmployee = await employeeRepository.findOne(3);
|
||||
console.log("Non exist employee: ", thirdEmployee);
|
||||
console.log("-----------------");
|
||||
const secondHomesitter = await homesitterRepository.findOne(1);
|
||||
console.log("Non exist homesitter: ", secondHomesitter);
|
||||
const thirdHomesitter = await homesitterRepository.findOne(3);
|
||||
console.log("Non exist homesitter: ", thirdHomesitter);
|
||||
console.log("-----------------");
|
||||
const secondStudent = await studentRepository.findOne(1);
|
||||
console.log("Non exist student: ", secondStudent);
|
||||
const thirdStudent = await studentRepository.findOne(2);
|
||||
console.log("Non exist student: ", thirdStudent);*/
|
||||
|
||||
}).catch(error => console.log("Error: ", error));
|
||||
@ -1,11 +0,0 @@
|
||||
import {Column} from "../../../src/decorator/columns/Column";
|
||||
import {Person} from "./Person";
|
||||
import {ClassEntityChild} from "../../../src/decorator/entity/ClassEntityChild";
|
||||
|
||||
@ClassEntityChild("sample29_employee")
|
||||
export class Employee extends Person {
|
||||
|
||||
@Column()
|
||||
salary: number;
|
||||
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
import {Column} from "../../../src/decorator/columns/Column";
|
||||
import {Person} from "./Person";
|
||||
import {DiscriminatorValue} from "../../../src/decorator/DiscriminatorValue";
|
||||
import {ClassEntityChild} from "../../../src/decorator/entity/ClassEntityChild";
|
||||
|
||||
@ClassEntityChild("sample29_homesitter")
|
||||
@DiscriminatorValue("home-sitter") // can be omitted
|
||||
export class Homesitter extends Person {
|
||||
|
||||
@Column()
|
||||
numberOfKids: number;
|
||||
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import {Column} from "../../../src/decorator/columns/Column";
|
||||
import {TableInheritance} from "../../../src/decorator/entity/TableInheritance";
|
||||
import {DiscriminatorColumn} from "../../../src/decorator/columns/DiscriminatorColumn";
|
||||
import {Entity} from "../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../src/decorator/columns/PrimaryColumn";
|
||||
|
||||
@Entity("sample29_person")
|
||||
@TableInheritance("class-table")
|
||||
@DiscriminatorColumn({ name: "type", type: "varchar" })
|
||||
export abstract class Person {
|
||||
|
||||
@PrimaryColumn("int")
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
firstName: string;
|
||||
|
||||
@Column()
|
||||
lastName: string;
|
||||
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
import {Column} from "../../../src/decorator/columns/Column";
|
||||
import {Person} from "./Person";
|
||||
import {ClassEntityChild} from "../../../src/decorator/entity/ClassEntityChild";
|
||||
|
||||
@ClassEntityChild("sample29_student")
|
||||
@ClassEntityChild()
|
||||
export class Student extends Person {
|
||||
|
||||
@Column()
|
||||
faculty: string;
|
||||
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
import {getMetadataArgsStorage} from "../index";
|
||||
import {DiscriminatorValueMetadataArgs} from "../metadata-args/DiscriminatorValueMetadataArgs";
|
||||
|
||||
/**
|
||||
* If entity is a child table of some table, it should have a discriminator value.
|
||||
* This decorator sets custom discriminator value for the entity.
|
||||
*/
|
||||
export function DiscriminatorValue(value: any): Function {
|
||||
return function (target: Function) {
|
||||
const args: DiscriminatorValueMetadataArgs = {
|
||||
target: target,
|
||||
value: value
|
||||
};
|
||||
getMetadataArgsStorage().discriminatorValues.push(args);
|
||||
};
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
import {ColumnOptions} from "../options/ColumnOptions";
|
||||
import {ColumnType} from "../../driver/types/ColumnTypes";
|
||||
import {getMetadataArgsStorage} from "../../index";
|
||||
import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
|
||||
|
||||
/**
|
||||
* DiscriminatorColumn is a special type column used on entity class (not entity property)
|
||||
* and creates a special column which will contain an entity type.
|
||||
* This type is required for entities which use single table inheritance pattern.
|
||||
*/
|
||||
export function DiscriminatorColumn(discriminatorOptions: { name: string, type: ColumnType }): Function {
|
||||
return function (target: Function) {
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
const options: ColumnOptions = {
|
||||
name: discriminatorOptions.name,
|
||||
type: discriminatorOptions.type
|
||||
};
|
||||
|
||||
// create and register a new column metadata
|
||||
const args: ColumnMetadataArgs = {
|
||||
target: target,
|
||||
mode: "discriminator",
|
||||
propertyName: discriminatorOptions.name,
|
||||
options: options
|
||||
};
|
||||
getMetadataArgsStorage().columns.push(args);
|
||||
};
|
||||
}
|
||||
|
||||
28
src/decorator/entity/ChildEntity.ts
Normal file
28
src/decorator/entity/ChildEntity.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import {getMetadataArgsStorage} from "../../index";
|
||||
import {TableMetadataArgs} from "../../metadata-args/TableMetadataArgs";
|
||||
import {DiscriminatorValueMetadataArgs} from "../../metadata-args/DiscriminatorValueMetadataArgs";
|
||||
|
||||
/**
|
||||
* Special type of the table used in the single-table inherited tables.
|
||||
*/
|
||||
export function ChildEntity(discriminatorValue?: string) {
|
||||
return function (target: Function) {
|
||||
|
||||
const tableMetadataArgs: TableMetadataArgs = {
|
||||
target: target,
|
||||
name: undefined,
|
||||
type: "entity-child",
|
||||
orderBy: undefined
|
||||
};
|
||||
getMetadataArgsStorage().tables.push(tableMetadataArgs);
|
||||
|
||||
if (discriminatorValue) {
|
||||
const discriminatorValueMetadataArgs: DiscriminatorValueMetadataArgs = {
|
||||
target: target,
|
||||
value: discriminatorValue
|
||||
};
|
||||
getMetadataArgsStorage().discriminatorValues.push(discriminatorValueMetadataArgs);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
import {getMetadataArgsStorage} from "../../index";
|
||||
import {TableMetadataArgs} from "../../metadata-args/TableMetadataArgs";
|
||||
import {EntityOptions} from "../options/EntityOptions";
|
||||
|
||||
/**
|
||||
* Special type of the entity used in the class-table inherited tables.
|
||||
*/
|
||||
export function ClassEntityChild(tableName?: string, options?: EntityOptions) {
|
||||
return function (target: Function) {
|
||||
const args: TableMetadataArgs = {
|
||||
target: target,
|
||||
name: tableName,
|
||||
type: "class-table-child",
|
||||
orderBy: options && options.orderBy ? options.orderBy : undefined,
|
||||
skipSync: !!(options && options.skipSync === true)
|
||||
};
|
||||
getMetadataArgsStorage().tables.push(args);
|
||||
};
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
import {getMetadataArgsStorage} from "../../index";
|
||||
import {TableMetadataArgs} from "../../metadata-args/TableMetadataArgs";
|
||||
|
||||
/**
|
||||
* Special type of the table used in the single-table inherited tables.
|
||||
*/
|
||||
export function SingleEntityChild() {
|
||||
return function (target: Function) {
|
||||
const args: TableMetadataArgs = {
|
||||
target: target,
|
||||
name: undefined,
|
||||
type: "single-table-child",
|
||||
orderBy: undefined
|
||||
};
|
||||
getMetadataArgsStorage().tables.push(args);
|
||||
};
|
||||
}
|
||||
@ -1,14 +1,16 @@
|
||||
import {getMetadataArgsStorage} from "../../index";
|
||||
import {InheritanceMetadataArgs} from "../../metadata-args/InheritanceMetadataArgs";
|
||||
import {ColumnOptions} from "../options/ColumnOptions";
|
||||
|
||||
/**
|
||||
* Sets what kind of table-inheritance table will use.
|
||||
* Sets for entity to use table inheritance pattern.
|
||||
*/
|
||||
export function TableInheritance(type: "single-table"|"class-table") { // todo: create two decorators instead?
|
||||
export function TableInheritance(options?: { pattern?: "STI"/*|"CTI"*/, column?: string|ColumnOptions }) {
|
||||
return function (target: Function) {
|
||||
const args: InheritanceMetadataArgs = {
|
||||
target: target,
|
||||
type: type
|
||||
pattern: options && options.pattern ? options.pattern : "STI",
|
||||
column: options && options.column ? typeof options.column === "string" ? { name: options.column } : options.column : undefined
|
||||
};
|
||||
getMetadataArgsStorage().inheritances.push(args);
|
||||
};
|
||||
|
||||
@ -26,7 +26,6 @@ export * from "./common/ObjectLiteral";
|
||||
export * from "./error/QueryFailedError";
|
||||
export * from "./decorator/columns/Column";
|
||||
export * from "./decorator/columns/CreateDateColumn";
|
||||
export * from "./decorator/columns/DiscriminatorColumn";
|
||||
export * from "./decorator/columns/PrimaryGeneratedColumn";
|
||||
export * from "./decorator/columns/PrimaryColumn";
|
||||
export * from "./decorator/columns/UpdateDateColumn";
|
||||
@ -56,9 +55,8 @@ export * from "./decorator/relations/OneToOne";
|
||||
export * from "./decorator/relations/RelationCount";
|
||||
export * from "./decorator/relations/RelationId";
|
||||
export * from "./decorator/entity/Entity";
|
||||
export * from "./decorator/entity/ClassEntityChild";
|
||||
export * from "./decorator/entity/ClosureEntity";
|
||||
export * from "./decorator/entity/SingleEntityChild";
|
||||
export * from "./decorator/entity/ChildEntity";
|
||||
export * from "./decorator/entity/TableInheritance";
|
||||
export * from "./decorator/transaction/Transaction";
|
||||
export * from "./decorator/transaction/TransactionManager";
|
||||
@ -68,7 +66,6 @@ export * from "./decorator/tree/TreeParent";
|
||||
export * from "./decorator/tree/TreeChildren";
|
||||
export * from "./decorator/Index";
|
||||
export * from "./decorator/Generated";
|
||||
export * from "./decorator/DiscriminatorValue";
|
||||
export * from "./decorator/EntityRepository";
|
||||
export * from "./find-options/FindOneOptions";
|
||||
export * from "./find-options/FindManyOptions";
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import {ColumnOptions} from "../decorator/options/ColumnOptions";
|
||||
|
||||
/**
|
||||
* Arguments for InheritanceMetadata class.
|
||||
*/
|
||||
@ -9,8 +11,13 @@ export interface InheritanceMetadataArgs {
|
||||
readonly target?: Function|string;
|
||||
|
||||
/**
|
||||
* Inheritance type.
|
||||
* Inheritance pattern.
|
||||
*/
|
||||
readonly type: "single-table"|"class-table";
|
||||
readonly pattern: "STI"/*|"CTI"*/;
|
||||
|
||||
/**
|
||||
* Column used as inheritance discriminator column.
|
||||
*/
|
||||
readonly column?: ColumnOptions;
|
||||
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ export class MetadataArgsStorage {
|
||||
return table.target instanceof Function
|
||||
&& target instanceof Function
|
||||
&& MetadataUtils.isInherited(table.target, target)
|
||||
&& table.type === "single-table-child";
|
||||
&& table.type === "entity-child";
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -4,4 +4,4 @@
|
||||
* For example, "primary" means that it will be a primary column, or "createDate" means that it will create a create
|
||||
* date column.
|
||||
*/
|
||||
export type ColumnMode = "regular"|"virtual"|"createDate"|"updateDate"|"version"|"treeChildrenCount"|"treeLevel"|"discriminator"|"parentId"|"objectId"|"array";
|
||||
export type ColumnMode = "regular"|"virtual"|"createDate"|"updateDate"|"version"|"treeChildrenCount"|"treeLevel"|"objectId"|"array";
|
||||
|
||||
@ -14,8 +14,6 @@ import {ClosureJunctionEntityMetadataBuilder} from "./ClosureJunctionEntityMetad
|
||||
import {RelationJoinColumnBuilder} from "./RelationJoinColumnBuilder";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {EntityListenerMetadata} from "../metadata/EntityListenerMetadata";
|
||||
import {ColumnOptions} from "../decorator/options/ColumnOptions";
|
||||
import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata";
|
||||
import {LazyRelationsWrapper} from "../lazy-loading/LazyRelationsWrapper";
|
||||
|
||||
/**
|
||||
@ -67,7 +65,7 @@ export class EntityMetadataBuilder {
|
||||
const allTables = entityClasses ? this.metadataArgsStorage.filterTables(entityClasses) : this.metadataArgsStorage.tables;
|
||||
|
||||
// filter out table metadata args for those we really create entity metadatas and tables in the db
|
||||
const realTables = allTables.filter(table => table.type === "regular" || table.type === "closure" || table.type === "class-table-child" || table.type === "single-table-child");
|
||||
const realTables = allTables.filter(table => table.type === "regular" || table.type === "closure" || table.type === "entity-child");
|
||||
|
||||
// create entity metadatas for a user defined entities (marked with @Entity decorator or loaded from entity schemas)
|
||||
const entityMetadatas = realTables.map(tableArgs => this.createEntityMetadata(tableArgs));
|
||||
@ -77,22 +75,22 @@ export class EntityMetadataBuilder {
|
||||
|
||||
// build entity metadata (step0), first for non-single-table-inherited entity metadatas (dependant)
|
||||
entityMetadatas
|
||||
.filter(entityMetadata => entityMetadata.tableType !== "single-table-child")
|
||||
.filter(entityMetadata => entityMetadata.tableType !== "entity-child")
|
||||
.forEach(entityMetadata => entityMetadata.build());
|
||||
|
||||
// build entity metadata (step0), now for single-table-inherited entity metadatas (dependant)
|
||||
entityMetadatas
|
||||
.filter(entityMetadata => entityMetadata.tableType === "single-table-child")
|
||||
.filter(entityMetadata => entityMetadata.tableType === "entity-child")
|
||||
.forEach(entityMetadata => entityMetadata.build());
|
||||
|
||||
// compute entity metadata columns, relations, etc. first for the regular, non-single-table-inherited entity metadatas
|
||||
entityMetadatas
|
||||
.filter(entityMetadata => entityMetadata.tableType !== "single-table-child")
|
||||
.filter(entityMetadata => entityMetadata.tableType !== "entity-child")
|
||||
.forEach(entityMetadata => this.computeEntityMetadataStep1(entityMetadatas, entityMetadata));
|
||||
|
||||
// then do it for single table inheritance children (since they are depend on their parents to be built)
|
||||
entityMetadatas
|
||||
.filter(entityMetadata => entityMetadata.tableType === "single-table-child")
|
||||
.filter(entityMetadata => entityMetadata.tableType === "entity-child")
|
||||
.forEach(entityMetadata => this.computeEntityMetadataStep1(entityMetadatas, entityMetadata));
|
||||
|
||||
// calculate entity metadata computed properties and all its sub-metadatas
|
||||
@ -103,7 +101,7 @@ export class EntityMetadataBuilder {
|
||||
|
||||
// go through all entity metadatas and create foreign keys / junction entity metadatas for their relations
|
||||
entityMetadatas
|
||||
.filter(entityMetadata => entityMetadata.tableType !== "single-table-child")
|
||||
.filter(entityMetadata => entityMetadata.tableType !== "entity-child")
|
||||
.forEach(entityMetadata => {
|
||||
|
||||
// create entity's relations join columns (for many-to-one and one-to-one owner)
|
||||
@ -148,7 +146,7 @@ export class EntityMetadataBuilder {
|
||||
entityMetadatas.push(closureJunctionEntityMetadata);
|
||||
});
|
||||
|
||||
// after all metadatas created we set child entity metadatas for class-table inheritance
|
||||
// after all metadatas created we set child entity metadatas for table inheritance
|
||||
entityMetadatas.forEach(metadata => {
|
||||
metadata.childEntityMetadatas = entityMetadatas.filter(childMetadata => {
|
||||
return metadata.target instanceof Function
|
||||
@ -159,7 +157,7 @@ export class EntityMetadataBuilder {
|
||||
|
||||
// generate keys for tables with single-table inheritance
|
||||
entityMetadatas
|
||||
.filter(metadata => metadata.inheritanceType === "single-table" && metadata.discriminatorColumn)
|
||||
.filter(metadata => metadata.inheritancePattern === "STI" && metadata.discriminatorColumn)
|
||||
.forEach(entityMetadata => this.createKeysForTableInheritance(entityMetadata));
|
||||
|
||||
// build all indices (need to do it after relations and their join columns are built)
|
||||
@ -167,46 +165,6 @@ export class EntityMetadataBuilder {
|
||||
entityMetadata.indices.forEach(index => index.build(this.connection.namingStrategy));
|
||||
});
|
||||
|
||||
entityMetadatas
|
||||
.filter(metadata => !!metadata.parentEntityMetadata && metadata.tableType === "class-table-child")
|
||||
.forEach(metadata => {
|
||||
const parentPrimaryColumns = metadata.parentEntityMetadata.primaryColumns;
|
||||
const parentRelationColumns = parentPrimaryColumns.map(parentPrimaryColumn => {
|
||||
const columnName = this.connection.namingStrategy.classTableInheritanceParentColumnName(metadata.parentEntityMetadata.tableName, parentPrimaryColumn.propertyPath);
|
||||
const column = new ColumnMetadata({
|
||||
connection: this.connection,
|
||||
entityMetadata: metadata,
|
||||
referencedColumn: parentPrimaryColumn,
|
||||
args: {
|
||||
target: metadata.target,
|
||||
propertyName: columnName,
|
||||
mode: "parentId",
|
||||
options: <ColumnOptions> {
|
||||
name: columnName,
|
||||
type: parentPrimaryColumn.type,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
primary: true
|
||||
}
|
||||
}
|
||||
});
|
||||
metadata.registerColumn(column);
|
||||
column.build(this.connection);
|
||||
return column;
|
||||
});
|
||||
|
||||
metadata.foreignKeys = [
|
||||
new ForeignKeyMetadata({
|
||||
entityMetadata: metadata,
|
||||
referencedEntityMetadata: metadata.parentEntityMetadata,
|
||||
namingStrategy: this.connection.namingStrategy,
|
||||
columns: parentRelationColumns,
|
||||
referencedColumns: parentPrimaryColumns,
|
||||
onDelete: "CASCADE"
|
||||
})
|
||||
];
|
||||
});
|
||||
|
||||
// add lazy initializer for entity relations
|
||||
entityMetadatas
|
||||
.filter(metadata => metadata.target instanceof Function)
|
||||
@ -258,43 +216,37 @@ export class EntityMetadataBuilder {
|
||||
|
||||
// if single table inheritance used, we need to copy all children columns in to parent table
|
||||
let singleTableChildrenTargets: any[];
|
||||
if ((tableInheritance && tableInheritance.type === "single-table") || tableArgs.type === "single-table-child") {
|
||||
if ((tableInheritance && tableInheritance.pattern === "STI") || tableArgs.type === "entity-child") {
|
||||
singleTableChildrenTargets = this.metadataArgsStorage
|
||||
.filterSingleTableChildren(tableArgs.target)
|
||||
.map(args => args.target)
|
||||
.filter(target => target instanceof Function);
|
||||
|
||||
inheritanceTree.push(...singleTableChildrenTargets);
|
||||
|
||||
} else if ((tableInheritance && tableInheritance.type === "class-table") || tableArgs.type === "class-table-child") {
|
||||
inheritanceTree.forEach(inheritanceTreeItem => {
|
||||
const isParent = !!this.metadataArgsStorage.inheritances.find(i => i.target === inheritanceTreeItem);
|
||||
if (isParent)
|
||||
inheritanceTree.splice(inheritanceTree.indexOf(inheritanceTreeItem), 1);
|
||||
});
|
||||
}
|
||||
|
||||
return new EntityMetadata({
|
||||
connection: this.connection,
|
||||
args: tableArgs,
|
||||
inheritanceTree: inheritanceTree,
|
||||
inheritanceType: tableInheritance ? tableInheritance.type : undefined
|
||||
inheritancePattern: tableInheritance ? tableInheritance.pattern : undefined
|
||||
});
|
||||
}
|
||||
|
||||
protected computeParentEntityMetadata(allEntityMetadatas: EntityMetadata[], entityMetadata: EntityMetadata) {
|
||||
|
||||
// after all metadatas created we set parent entity metadata for table inheritance
|
||||
if (entityMetadata.tableType === "single-table-child" || entityMetadata.tableType === "class-table-child") {
|
||||
if (entityMetadata.tableType === "entity-child") {
|
||||
entityMetadata.parentEntityMetadata = allEntityMetadatas.find(allEntityMetadata => {
|
||||
return allEntityMetadata.inheritanceTree.indexOf(entityMetadata.target as Function) !== -1 &&
|
||||
(allEntityMetadata.inheritanceType === "single-table" || allEntityMetadata.inheritanceType === "class-table");
|
||||
return allEntityMetadata.inheritanceTree.indexOf(entityMetadata.target as Function) !== -1 && allEntityMetadata.inheritancePattern === "STI";
|
||||
})!;
|
||||
}
|
||||
}
|
||||
|
||||
protected computeEntityMetadataStep1(allEntityMetadatas: EntityMetadata[], entityMetadata: EntityMetadata) {
|
||||
|
||||
const entityInheritance = this.metadataArgsStorage.findInheritanceType(entityMetadata.target);
|
||||
|
||||
const discriminatorValue = this.metadataArgsStorage.findDiscriminatorValue(entityMetadata.target);
|
||||
entityMetadata.discriminatorValue = discriminatorValue ? discriminatorValue.value : (entityMetadata.target as any).name; // todo: pass this to naming strategy to generate a name
|
||||
|
||||
@ -304,22 +256,50 @@ export class EntityMetadataBuilder {
|
||||
.map(args => {
|
||||
|
||||
// for single table children we reuse columns created for their parents
|
||||
if (entityMetadata.tableType === "single-table-child")
|
||||
if (entityMetadata.tableType === "entity-child")
|
||||
return entityMetadata.parentEntityMetadata.ownColumns.find(column => column.propertyName === args.propertyName)!;
|
||||
|
||||
const column = new ColumnMetadata({ connection: this.connection, entityMetadata, args });
|
||||
|
||||
// if single table inheritance used, we need to mark all inherit table columns as nullable
|
||||
const columnInSingleTableInheritedChild = allEntityMetadatas.find(otherEntityMetadata => otherEntityMetadata.tableType === "single-table-child" && otherEntityMetadata.target === args.target);
|
||||
const columnInSingleTableInheritedChild = allEntityMetadatas.find(otherEntityMetadata => otherEntityMetadata.tableType === "entity-child" && otherEntityMetadata.target === args.target);
|
||||
if (columnInSingleTableInheritedChild)
|
||||
column.isNullable = true;
|
||||
return column;
|
||||
});
|
||||
|
||||
// for table inheritance we need to add a discriminator column
|
||||
//
|
||||
if (entityInheritance && entityInheritance.column) {
|
||||
const discriminatorColumnName = entityInheritance.column && entityInheritance.column.name ? entityInheritance.column.name : "type";
|
||||
let discriminatorColumn = entityMetadata.ownColumns.find(column => column.propertyName === discriminatorColumnName);
|
||||
if (!discriminatorColumn) {
|
||||
discriminatorColumn = new ColumnMetadata({
|
||||
connection: this.connection,
|
||||
entityMetadata: entityMetadata,
|
||||
args: {
|
||||
target: entityMetadata.target,
|
||||
mode: "virtual",
|
||||
propertyName: discriminatorColumnName,
|
||||
options: entityInheritance.column || {
|
||||
name: "type",
|
||||
type: "varchar",
|
||||
nullable: false
|
||||
}
|
||||
}
|
||||
});
|
||||
discriminatorColumn.isVirtual = true;
|
||||
discriminatorColumn.isDiscriminator = true;
|
||||
entityMetadata.ownColumns.push(discriminatorColumn);
|
||||
} else {
|
||||
discriminatorColumn.isDiscriminator = true;
|
||||
}
|
||||
}
|
||||
|
||||
entityMetadata.ownRelations = this.metadataArgsStorage.filterRelations(entityMetadata.inheritanceTree).map(args => {
|
||||
|
||||
// for single table children we reuse relations created for their parents
|
||||
if (entityMetadata.tableType === "single-table-child")
|
||||
if (entityMetadata.tableType === "entity-child")
|
||||
return entityMetadata.parentEntityMetadata.ownRelations.find(relation => relation.propertyName === args.propertyName)!;
|
||||
|
||||
return new RelationMetadata({ entityMetadata, args });
|
||||
@ -327,7 +307,7 @@ export class EntityMetadataBuilder {
|
||||
entityMetadata.relationIds = this.metadataArgsStorage.filterRelationIds(entityMetadata.inheritanceTree).map(args => {
|
||||
|
||||
// for single table children we reuse relation ids created for their parents
|
||||
if (entityMetadata.tableType === "single-table-child")
|
||||
if (entityMetadata.tableType === "entity-child")
|
||||
return entityMetadata.parentEntityMetadata.relationIds.find(relationId => relationId.propertyName === args.propertyName)!;
|
||||
|
||||
return new RelationIdMetadata({ entityMetadata, args });
|
||||
@ -335,7 +315,7 @@ export class EntityMetadataBuilder {
|
||||
entityMetadata.relationCounts = this.metadataArgsStorage.filterRelationCounts(entityMetadata.inheritanceTree).map(args => {
|
||||
|
||||
// for single table children we reuse relation counts created for their parents
|
||||
if (entityMetadata.tableType === "single-table-child")
|
||||
if (entityMetadata.tableType === "entity-child")
|
||||
return entityMetadata.parentEntityMetadata.relationCounts.find(relationCount => relationCount.propertyName === args.propertyName)!;
|
||||
|
||||
return new RelationCountMetadata({ entityMetadata, args });
|
||||
@ -424,7 +404,6 @@ export class EntityMetadataBuilder {
|
||||
entityMetadata.versionColumn = entityMetadata.columns.find(column => column.isVersion);
|
||||
entityMetadata.discriminatorColumn = entityMetadata.columns.find(column => column.isDiscriminator);
|
||||
entityMetadata.treeLevelColumn = entityMetadata.columns.find(column => column.isTreeLevel);
|
||||
entityMetadata.parentIdColumns = entityMetadata.columns.filter(column => column.isParentId);
|
||||
entityMetadata.objectIdColumn = entityMetadata.columns.find(column => column.isObjectId);
|
||||
entityMetadata.foreignKeys.forEach(foreignKey => foreignKey.build(this.connection.namingStrategy));
|
||||
entityMetadata.propertiesMap = entityMetadata.createPropertiesMap();
|
||||
@ -479,135 +458,4 @@ export class EntityMetadataBuilder {
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// generate virtual column with foreign key for class-table inheritance
|
||||
/*entityMetadatas.forEach(entityMetadata => {
|
||||
if (!entityMetadata.parentEntityMetadata)
|
||||
return;
|
||||
|
||||
const parentPrimaryColumns = entityMetadata.parentEntityMetadata.primaryColumns;
|
||||
const parentIdColumns = parentPrimaryColumns.map(primaryColumn => {
|
||||
const columnName = this.namingStrategy.classTableInheritanceParentColumnName(entityMetadata.parentEntityMetadata.tableName, primaryColumn.propertyName);
|
||||
const column = new ColumnMetadataBuilder(entityMetadata);
|
||||
column.type = primaryColumn.type;
|
||||
column.propertyName = primaryColumn.propertyName; // todo: check why needed
|
||||
column.givenName = columnName;
|
||||
column.mode = "parentId";
|
||||
column.isUnique = true;
|
||||
column.isNullable = false;
|
||||
// column.entityTarget = entityMetadata.target;
|
||||
return column;
|
||||
});
|
||||
|
||||
// add foreign key
|
||||
const foreignKey = new ForeignKeyMetadataBuilder(
|
||||
entityMetadata,
|
||||
parentIdColumns,
|
||||
entityMetadata.parentEntityMetadata,
|
||||
parentPrimaryColumns,
|
||||
"CASCADE"
|
||||
);
|
||||
entityMetadata.ownColumns.push(...parentIdColumns);
|
||||
entityMetadata.foreignKeys.push(foreignKey);
|
||||
});*/
|
||||
|
||||
|
||||
/*protected createEntityMetadata(metadata: EntityMetadata, options: {
|
||||
userSpecifiedTableName?: string,
|
||||
closureOwnerTableName?: string,
|
||||
}) {
|
||||
|
||||
const tableNameUserSpecified = options.userSpecifiedTableName;
|
||||
const isClosureJunction = metadata.tableType === "closure-junction";
|
||||
const targetName = metadata.target instanceof Function ? (metadata.target as any).name : metadata.target;
|
||||
const tableNameWithoutPrefix = isClosureJunction
|
||||
? this.namingStrategy.closureJunctionTableName(options.closureOwnerTableName!)
|
||||
: this.namingStrategy.tableName(targetName, options.userSpecifiedTableName);
|
||||
|
||||
const tableName = this.namingStrategy.prefixTableName(this.driver.options.tablesPrefix, tableNameWithoutPrefix);
|
||||
|
||||
// for virtual tables (like junction table) target is equal to undefined at this moment
|
||||
// we change this by setting virtual's table name to a target name
|
||||
// todo: add validation so targets with same schema names won't conflicts with virtual table names
|
||||
metadata.target = metadata.target ? metadata.target : tableName;
|
||||
metadata.targetName = targetName;
|
||||
metadata.givenTableName = tableNameUserSpecified;
|
||||
metadata.tableNameWithoutPrefix = tableNameWithoutPrefix;
|
||||
metadata.tableName = tableName;
|
||||
metadata.name = targetName ? targetName : tableName;
|
||||
// metadata.namingStrategy = this.namingStrategy;
|
||||
}*/
|
||||
|
||||
/*protected createEntityMetadata(tableArgs: any, argsForTable: any, ): EntityMetadata {
|
||||
const metadata = new EntityMetadata({
|
||||
junction: false,
|
||||
target: tableArgs.target,
|
||||
tablesPrefix: this.driver.options.tablesPrefix,
|
||||
namingStrategy: this.namingStrategy,
|
||||
tableName: argsForTable.name,
|
||||
tableType: argsForTable.type,
|
||||
orderBy: argsForTable.orderBy,
|
||||
engine: argsForTable.engine,
|
||||
skipSchemaSync: argsForTable.skipSchemaSync,
|
||||
columnMetadatas: columns,
|
||||
relationMetadatas: relations,
|
||||
relationIdMetadatas: relationIds,
|
||||
relationCountMetadatas: relationCounts,
|
||||
indexMetadatas: indices,
|
||||
embeddedMetadatas: embeddeds,
|
||||
inheritanceType: mergedArgs.inheritance ? mergedArgs.inheritance.type : undefined,
|
||||
discriminatorValue: discriminatorValueArgs ? discriminatorValueArgs.value : (tableArgs.target as any).name // todo: pass this to naming strategy to generate a name
|
||||
}, this.lazyRelationsWrapper);
|
||||
return metadata;
|
||||
}*/
|
||||
|
||||
|
||||
// const tables = [mergedArgs.table].concat(mergedArgs.children);
|
||||
// tables.forEach(tableArgs => {
|
||||
|
||||
// find embeddable tables for embeddeds registered in this table and create EmbeddedMetadatas from them
|
||||
// const findEmbeddedsRecursively = (embeddedArgs: EmbeddedMetadataArgs[]) => {
|
||||
// const embeddeds: EmbeddedMetadata[] = [];
|
||||
// embeddedArgs.forEach(embedded => {
|
||||
// const embeddableTable = embeddableMergedArgs.find(embeddedMergedArgs => embeddedMergedArgs.table.target === embedded.type());
|
||||
// if (embeddableTable) {
|
||||
// const columns = embeddableTable.columns.toArray().map(args => new ColumnMetadata(args));
|
||||
// const relations = embeddableTable.relations.toArray().map(args => new RelationMetadata(args));
|
||||
// const subEmbeddeds = findEmbeddedsRecursively(embeddableTable.embeddeds.toArray());
|
||||
// embeddeds.push(new EmbeddedMetadata(columns, relations, subEmbeddeds, embedded));
|
||||
// }
|
||||
// });
|
||||
// return embeddeds;
|
||||
// };
|
||||
// const embeddeds = findEmbeddedsRecursively(mergedArgs.embeddeds.toArray());
|
||||
|
||||
// create metadatas from args
|
||||
// const argsForTable = mergedArgs.inheritance && mergedArgs.inheritance.type === "single-table" ? mergedArgs.table : tableArgs;
|
||||
|
||||
// const table = new TableMetadata(argsForTable);
|
||||
// const columns = mergedArgs.columns.toArray().map(args => {
|
||||
//
|
||||
// // if column's target is a child table then this column should have all nullable columns
|
||||
// if (mergedArgs.inheritance &&
|
||||
// mergedArgs.inheritance.type === "single-table" &&
|
||||
// args.target !== mergedArgs.table.target && !!mergedArgs.children.find(childTable => childTable.target === args.target)) {
|
||||
// args.options.nullable = true;
|
||||
// }
|
||||
// return new ColumnMetadata(args);
|
||||
// });
|
||||
// const discriminatorValueArgs = mergedArgs.discriminatorValues.find(discriminatorValueArgs => {
|
||||
// return discriminatorValueArgs.target === tableArgs.target;
|
||||
// });
|
||||
|
||||
|
||||
|
||||
// after all metadatas created we set parent entity metadata for class-table inheritance
|
||||
// entityMetadatas.forEach(entityMetadata => {
|
||||
// const mergedArgs = realTables.find(args => args.target === entityMetadata.target);
|
||||
// if (mergedArgs && mergedArgs.parent) {
|
||||
// const parentEntityMetadata = entityMetadatas.find(entityMetadata => entityMetadata.target === (mergedArgs!.parent! as any).target); // todo: weird compiler error here, thats why type casing is used
|
||||
// if (parentEntityMetadata)
|
||||
// entityMetadata.parentEntityMetadata = parentEntityMetadata;
|
||||
// }
|
||||
// });
|
||||
}
|
||||
@ -47,12 +47,12 @@ export class EntityMetadataValidator {
|
||||
validate(entityMetadata: EntityMetadata, allEntityMetadatas: EntityMetadata[], driver: Driver) {
|
||||
|
||||
// check if table metadata has an id
|
||||
if (!entityMetadata.isClassTableChild && !entityMetadata.primaryColumns.length && !entityMetadata.isJunction)
|
||||
if (!entityMetadata.primaryColumns.length && !entityMetadata.isJunction)
|
||||
throw new MissingPrimaryColumnError(entityMetadata);
|
||||
|
||||
// validate if table is using inheritance it has a discriminator
|
||||
// also validate if discriminator values are not empty and not repeated
|
||||
if (entityMetadata.inheritanceType === "single-table") {
|
||||
if (entityMetadata.inheritancePattern === "STI") {
|
||||
if (!entityMetadata.discriminatorColumn)
|
||||
throw new Error(`Entity ${entityMetadata.name} using single-table inheritance, it should also have a discriminator column. Did you forget to put @DiscriminatorColumn decorator?`);
|
||||
|
||||
|
||||
@ -175,11 +175,6 @@ export class ColumnMetadata {
|
||||
*/
|
||||
isVirtual: boolean = false;
|
||||
|
||||
/**
|
||||
* Indicates if column is a parent id. Parent id columns are not mapped to the entity.
|
||||
*/
|
||||
isParentId: boolean = false;
|
||||
|
||||
/**
|
||||
* Indicates if column is discriminator. Discriminator columns are not mapped to the entity.
|
||||
*/
|
||||
@ -286,8 +281,6 @@ export class ColumnMetadata {
|
||||
this.isArray = options.args.options.array;
|
||||
if (options.args.mode) {
|
||||
this.isVirtual = options.args.mode === "virtual";
|
||||
this.isParentId = options.args.mode === "parentId";
|
||||
this.isDiscriminator = options.args.mode === "discriminator";
|
||||
this.isTreeLevel = options.args.mode === "treeLevel";
|
||||
this.isCreateDate = options.args.mode === "createDate";
|
||||
this.isUpdateDate = options.args.mode === "updateDate";
|
||||
|
||||
@ -290,7 +290,7 @@ export class EntityMetadata {
|
||||
* If this entity metadata's table using one of the inheritance patterns,
|
||||
* then this will contain what pattern it uses.
|
||||
*/
|
||||
inheritanceType?: "single-table"|"class-table";
|
||||
inheritancePattern?: "STI"/*|"CTI"*/;
|
||||
|
||||
/**
|
||||
* If this entity metadata is a child table of some table, it should have a discriminator value.
|
||||
@ -348,11 +348,6 @@ export class EntityMetadata {
|
||||
*/
|
||||
primaryColumns: ColumnMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Id columns in the parent table (used in table inheritance).
|
||||
*/
|
||||
parentIdColumns: ColumnMetadata[] = [];
|
||||
|
||||
/**
|
||||
* Gets only one-to-one relations of the entity.
|
||||
*/
|
||||
@ -435,18 +430,6 @@ export class EntityMetadata {
|
||||
*/
|
||||
isEmbeddable: boolean;
|
||||
|
||||
/**
|
||||
* Checks if this table is a single table child.
|
||||
* Special table type for tables that are mapped into single table using Single Table Inheritance pattern.
|
||||
*/
|
||||
isSingleTableChild: boolean;
|
||||
|
||||
/**
|
||||
* Checks if this table is a class table child.
|
||||
* Special table type for tables that are mapped into multiple tables using Class Table Inheritance pattern.
|
||||
*/
|
||||
isClassTableChild: boolean;
|
||||
|
||||
/**
|
||||
* Map of columns and relations of the entity.
|
||||
*
|
||||
@ -463,13 +446,13 @@ export class EntityMetadata {
|
||||
constructor(options: {
|
||||
connection: Connection,
|
||||
inheritanceTree?: Function[],
|
||||
inheritanceType?: "single-table"|"class-table",
|
||||
inheritancePattern?: "STI"/*|"CTI"*/,
|
||||
parentClosureEntityMetadata?: EntityMetadata,
|
||||
args: TableMetadataArgs
|
||||
}) {
|
||||
this.connection = options.connection;
|
||||
this.inheritanceTree = options.inheritanceTree || [];
|
||||
this.inheritanceType = options.inheritanceType;
|
||||
this.inheritancePattern = options.inheritancePattern;
|
||||
this.lazyRelationsWrapper = new LazyRelationsWrapper(options.connection);
|
||||
this.parentClosureEntityMetadata = options.parentClosureEntityMetadata!;
|
||||
this.tableMetadataArgs = options.args;
|
||||
@ -548,16 +531,14 @@ export class EntityMetadata {
|
||||
* Checks if there is an embedded with a given property path.
|
||||
*/
|
||||
hasEmbeddedWithPropertyPath(propertyPath: string): boolean {
|
||||
return !!this.findEmbeddedWithPropertyPath(propertyPath);
|
||||
return this.allEmbeddeds.some(embedded => embedded.propertyPath === propertyPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds embedded with a given property path.
|
||||
*/
|
||||
findEmbeddedWithPropertyPath(propertyPath: string): EmbeddedMetadata|undefined {
|
||||
return this.allEmbeddeds.find(embedded => {
|
||||
return embedded.propertyPath === propertyPath;
|
||||
});
|
||||
return this.allEmbeddeds.find(embedded => embedded.propertyPath === propertyPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -699,24 +680,6 @@ export class EntityMetadata {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as getEntityIdMap, but instead of id column property names it returns database column names.
|
||||
*/
|
||||
getDatabaseEntityIdMap(entity: ObjectLiteral): ObjectLiteral|undefined {
|
||||
const map: ObjectLiteral = {};
|
||||
this.primaryColumns.forEach(column => {
|
||||
const entityValue = column.getEntityValue(entity);
|
||||
if (entityValue === null || entityValue === undefined)
|
||||
return;
|
||||
|
||||
map[column.databaseName] = entityValue;
|
||||
});
|
||||
const hasAllIds = Object.keys(map).every(key => {
|
||||
return map[key] !== undefined && map[key] !== null;
|
||||
});
|
||||
return hasAllIds ? map : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a "mixed id map".
|
||||
* If entity has multiple primary keys (ids) then it will return just regular id map, like what getEntityIdMap returns.
|
||||
@ -775,7 +738,6 @@ export class EntityMetadata {
|
||||
registerColumn(column: ColumnMetadata) {
|
||||
this.ownColumns.push(column);
|
||||
this.columns = this.embeddeds.reduce((columns, embedded) => columns.concat(embedded.columnsFromTree), this.ownColumns);
|
||||
this.parentIdColumns = this.columns.filter(column => column.isParentId);
|
||||
this.primaryColumns = this.columns.filter(column => column.isPrimary);
|
||||
this.hasMultiplePrimaryKeys = this.primaryColumns.length > 1;
|
||||
this.hasUUIDGeneratedColumns = this.columns.filter(column => column.isGenerated || column.generationStrategy === "uuid").length > 0;
|
||||
@ -807,12 +769,12 @@ export class EntityMetadata {
|
||||
this.engine = this.tableMetadataArgs.engine;
|
||||
this.database = this.tableMetadataArgs.database;
|
||||
this.schema = this.tableMetadataArgs.schema;
|
||||
this.givenTableName = this.tableType === "single-table-child" && this.parentEntityMetadata ? this.parentEntityMetadata.givenTableName : this.tableMetadataArgs.name;
|
||||
this.givenTableName = this.tableType === "entity-child" && this.parentEntityMetadata ? this.parentEntityMetadata.givenTableName : this.tableMetadataArgs.name;
|
||||
this.skipSync = this.tableMetadataArgs.skipSync || false;
|
||||
this.targetName = this.tableMetadataArgs.target instanceof Function ? (this.tableMetadataArgs.target as any).name : this.tableMetadataArgs.target;
|
||||
if (this.tableType === "closure-junction") {
|
||||
this.tableNameWithoutPrefix = namingStrategy.closureJunctionTableName(this.givenTableName!);
|
||||
} else if (this.tableType === "single-table-child" && this.parentEntityMetadata) {
|
||||
} else if (this.tableType === "entity-child" && this.parentEntityMetadata) {
|
||||
this.tableNameWithoutPrefix = namingStrategy.tableName(this.parentEntityMetadata.targetName, this.parentEntityMetadata.givenTableName);
|
||||
} else {
|
||||
this.tableNameWithoutPrefix = namingStrategy.tableName(this.targetName, this.givenTableName);
|
||||
@ -824,8 +786,6 @@ export class EntityMetadata {
|
||||
this.schemaPath = this.buildSchemaPath();
|
||||
this.orderBy = (this.tableMetadataArgs.orderBy instanceof Function) ? this.tableMetadataArgs.orderBy(this.propertiesMap) : this.tableMetadataArgs.orderBy; // todo: is propertiesMap available here? Looks like its not
|
||||
|
||||
this.isClassTableChild = this.tableType === "class-table-child";
|
||||
this.isSingleTableChild = this.tableType === "single-table-child";
|
||||
this.isEmbeddable = this.tableType === "embeddable";
|
||||
this.isJunction = this.tableType === "closure-junction" || this.tableType === "junction";
|
||||
this.isClosureJunction = this.tableType === "closure-junction";
|
||||
|
||||
@ -2,4 +2,4 @@
|
||||
* Table type. Tables can be abstract, closure, junction, embedded, etc.
|
||||
*/
|
||||
export type TableType = "regular"|"abstract"|"junction"|"closure"|"closure-junction"|
|
||||
"embeddable"|"single-table-child"|"class-table-child";
|
||||
"embeddable"|"entity-child";
|
||||
|
||||
@ -69,10 +69,6 @@ export class DefaultNamingStrategy implements NamingStrategyInterface {
|
||||
return "fk_" + RandomGenerator.sha1(key).substr(0, 27); // todo: use crypto instead?
|
||||
}
|
||||
|
||||
classTableInheritanceParentColumnName(parentTableName: any, parentTableIdPropertyName: any): string {
|
||||
return camelCase(parentTableName + "_" + parentTableIdPropertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds globally set prefix to the table name.
|
||||
* This method is executed no matter if prefix was set or not.
|
||||
|
||||
@ -68,11 +68,6 @@ export interface NamingStrategyInterface {
|
||||
*/
|
||||
foreignKeyName(tableName: string, columnNames: string[], referencedTableName: string, referencedColumnNames: string[]): string;
|
||||
|
||||
/**
|
||||
* Gets the column name of the column with foreign key to the parent table used in the class table inheritance.
|
||||
*/
|
||||
classTableInheritanceParentColumnName(parentTableName: any, parentTableIdPropertyName: any): string;
|
||||
|
||||
/**
|
||||
* Adds globally set prefix to the table name.
|
||||
* This method is executed no matter if prefix was set or not.
|
||||
|
||||
@ -38,7 +38,6 @@ export class SubjectChangedColumnsComputer {
|
||||
|
||||
// ignore special columns
|
||||
if (column.isVirtual ||
|
||||
column.isParentId ||
|
||||
column.isDiscriminator ||
|
||||
column.isUpdateDate ||
|
||||
column.isVersion ||
|
||||
|
||||
@ -695,13 +695,6 @@ export abstract class QueryBuilder<Entity> {
|
||||
this.expressionMap.nativeParameters[parameterName] = primaryColumn.getEntityValue(id);
|
||||
parameterIndex++;
|
||||
});
|
||||
metadata.parentIdColumns.forEach((parentIdColumn, secondIndex) => {
|
||||
// whereSubStrings.push(alias + this.escape(parentIdColumn.databaseName) + "=:parentId_" + index + "_" + secondIndex);
|
||||
const parameterName = "parentId_" + index + "_" + secondIndex;
|
||||
whereSubStrings.push(alias + this.escape(parentIdColumn.databaseName) + " = " + this.connection.driver.createParameter(parameterName, parameterIndex));
|
||||
this.expressionMap.nativeParameters[parameterName] = parentIdColumn.getEntityValue(id);
|
||||
parameterIndex++;
|
||||
});
|
||||
return whereSubStrings.join(" AND ");
|
||||
});
|
||||
|
||||
|
||||
@ -148,11 +148,6 @@ export class QueryExpressionMap {
|
||||
*/
|
||||
disableEscaping: boolean = true;
|
||||
|
||||
/**
|
||||
* todo: needs more information.
|
||||
*/
|
||||
ignoreParentTablesJoins: boolean = false;
|
||||
|
||||
/**
|
||||
* Indicates if virtual columns should be included in entity result.
|
||||
*
|
||||
@ -382,7 +377,6 @@ export class QueryExpressionMap {
|
||||
map.lockVersion = this.lockVersion;
|
||||
map.parameters = Object.assign({}, this.parameters);
|
||||
map.disableEscaping = this.disableEscaping;
|
||||
map.ignoreParentTablesJoins = this.ignoreParentTablesJoins;
|
||||
map.enableRelationIdValues = this.enableRelationIdValues;
|
||||
map.extraAppendedAndWhereCondition = this.extraAppendedAndWhereCondition;
|
||||
map.subQuery = this.subQuery;
|
||||
|
||||
@ -1331,39 +1331,6 @@ export class SelectQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.expressionMap.ignoreParentTablesJoins && this.expressionMap.mainAlias.hasMetadata) {
|
||||
const metadata = this.expressionMap.mainAlias.metadata;
|
||||
if (metadata.parentEntityMetadata && metadata.parentEntityMetadata.inheritanceType === "class-table" && metadata.parentIdColumns) {
|
||||
const alias = "parentIdColumn_" + metadata.parentEntityMetadata.tableName;
|
||||
metadata.parentEntityMetadata.columns.forEach(column => {
|
||||
// TODO implement partial select
|
||||
allSelects.push({ selection: this.escape(alias) + "." + this.escape(column.databaseName), aliasName: alias + "_" + column.databaseName });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// add selects from relation id joins
|
||||
// this.relationIdAttributes.forEach(relationIdAttr => {
|
||||
// });
|
||||
|
||||
/*if (this.enableRelationIdValues) {
|
||||
const parentMetadata = this.aliasMap.getEntityMetadataByAlias(this.aliasMap.mainAlias);
|
||||
if (!parentMetadata)
|
||||
throw new Error("Cannot get entity metadata for the given alias " + this.aliasMap.mainAlias.name);
|
||||
|
||||
const metadata = this.connection.entityMetadatas.findByTarget(this.aliasMap.mainAlias.target);
|
||||
metadata.manyToManyRelations.forEach(relation => {
|
||||
|
||||
const junctionMetadata = relation.junctionEntityMetadata;
|
||||
junctionMetadata.columns.forEach(column => {
|
||||
const select = ea(this.aliasMap.mainAlias.name + "_" + junctionMetadata.table.name + "_ids") + "." +
|
||||
ec(column.name) + " AS " +
|
||||
ea(this.aliasMap.mainAlias.name + "_" + relation.name + "_ids_" + column.name);
|
||||
allSelects.push(select);
|
||||
});
|
||||
});
|
||||
}*/
|
||||
|
||||
// add all other selects
|
||||
this.expressionMap.selects
|
||||
.filter(select => excludedSelects.indexOf(select) === -1)
|
||||
@ -1487,18 +1454,6 @@ export class SelectQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.expressionMap.ignoreParentTablesJoins && this.expressionMap.mainAlias!.hasMetadata) {
|
||||
const metadata = this.expressionMap.mainAlias!.metadata;
|
||||
if (metadata.parentEntityMetadata && metadata.parentEntityMetadata.inheritanceType === "class-table" && metadata.parentIdColumns) {
|
||||
const alias = "parentIdColumn_" + metadata.parentEntityMetadata.tableName;
|
||||
const condition = metadata.parentIdColumns.map(parentIdColumn => {
|
||||
return this.expressionMap.mainAlias!.name + "." + parentIdColumn.propertyPath + " = " + this.escape(alias) + "." + this.escape(parentIdColumn.referencedColumn!.propertyPath);
|
||||
}).join(" AND ");
|
||||
const join = " JOIN " + this.getTableName(metadata.parentEntityMetadata.tableName) + " " + this.escape(alias) + " ON " + this.replacePropertyNames(condition);
|
||||
joins.push(join);
|
||||
}
|
||||
}
|
||||
|
||||
return joins.join(" ");
|
||||
}
|
||||
|
||||
@ -1721,7 +1676,6 @@ export class SelectQueryBuilder<Entity> extends QueryBuilder<Entity> implements
|
||||
}
|
||||
|
||||
const results = await this.clone()
|
||||
.mergeExpressionMap({ ignoreParentTablesJoins: true })
|
||||
.orderBy()
|
||||
.groupBy()
|
||||
.offset(undefined)
|
||||
|
||||
@ -72,9 +72,7 @@ export class DocumentToEntityTransformer {
|
||||
if (valueInObject !== undefined &&
|
||||
valueInObject !== null &&
|
||||
column.propertyName &&
|
||||
!column.isVirtual &&
|
||||
!column.isParentId &&
|
||||
!column.isDiscriminator) {
|
||||
!column.isVirtual) {
|
||||
// const value = this.driver.prepareHydratedValue(valueInObject, column);
|
||||
|
||||
entity[column.propertyName] = valueInObject;
|
||||
|
||||
@ -111,7 +111,7 @@ export class RawSqlResultsToEntityTransformer {
|
||||
return;
|
||||
|
||||
const value = rawResults[0][alias.name + "_" + column.databaseName];
|
||||
if (value === undefined || column.isVirtual || column.isParentId || column.isDiscriminator)
|
||||
if (value === undefined || column.isVirtual)
|
||||
return;
|
||||
|
||||
// if user does not selected the whole entity or he used partial selection and does not select this particular column
|
||||
@ -123,18 +123,6 @@ export class RawSqlResultsToEntityTransformer {
|
||||
if (value !== null) // we don't mark it as has data because if we will have all nulls in our object - we don't need such object
|
||||
hasData = true;
|
||||
});
|
||||
|
||||
if (metadata.parentEntityMetadata) { // todo: revisit
|
||||
metadata.parentEntityMetadata.columns.forEach(column => {
|
||||
const value = rawResults[0]["parentIdColumn_" + metadata.parentEntityMetadata.tableName + "_" + column.databaseName];
|
||||
if (value === undefined || column.isVirtual || column.isParentId || column.isDiscriminator)
|
||||
return;
|
||||
|
||||
column.setEntityValue(entity, this.driver.prepareHydratedValue(value, column));
|
||||
if (value !== null) // we don't mark it as has data because if we will have all nulls in our object - we don't need such object
|
||||
hasData = true;
|
||||
});
|
||||
}
|
||||
return hasData;
|
||||
}
|
||||
|
||||
|
||||
@ -123,7 +123,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder {
|
||||
* Returns only entities that should be synced in the database.
|
||||
*/
|
||||
protected get entityToSyncMetadatas(): EntityMetadata[] {
|
||||
return this.connection.entityMetadatas.filter(metadata => !metadata.skipSync && metadata.tableType !== "single-table-child");
|
||||
return this.connection.entityMetadatas.filter(metadata => !metadata.skipSync && metadata.tableType !== "entity-child");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,254 +0,0 @@
|
||||
import "reflect-metadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {Student} from "./entity/Student";
|
||||
import {Teacher} from "./entity/Teacher";
|
||||
import {Accountant} from "./entity/Accountant";
|
||||
|
||||
describe.skip("table-inheritance > class-table > basic-functionality", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should correctly insert, update and delete data with class-table-inheritance pattern", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Create
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
const student1 = new Student();
|
||||
student1.name = "Alice";
|
||||
student1.faculty = "Economics";
|
||||
await connection.getRepository(Student).save(student1);
|
||||
|
||||
const student2 = new Student();
|
||||
student2.name = "Bob";
|
||||
student2.faculty = "Programming";
|
||||
await connection.getRepository(Student).save(student2);
|
||||
|
||||
const teacher1 = new Teacher();
|
||||
teacher1.name = "Mr. Garrison";
|
||||
teacher1.specialization = "Geography";
|
||||
teacher1.salary = 2000;
|
||||
await connection.getRepository(Teacher).save(teacher1);
|
||||
|
||||
const teacher2 = new Teacher();
|
||||
teacher2.name = "Mr. Adler";
|
||||
teacher2.specialization = "Mathematics";
|
||||
teacher2.salary = 4000;
|
||||
await connection.getRepository(Teacher).save(teacher2);
|
||||
|
||||
const accountant1 = new Accountant();
|
||||
accountant1.name = "Mr. Burns";
|
||||
accountant1.department = "Bookkeeping";
|
||||
accountant1.salary = 3000;
|
||||
await connection.getRepository(Accountant).save(accountant1);
|
||||
|
||||
const accountant2 = new Accountant();
|
||||
accountant2.name = "Mr. Trump";
|
||||
accountant2.department = "Director";
|
||||
accountant2.salary = 5000;
|
||||
await connection.getRepository(Accountant).save(accountant2);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Select
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
let loadedStudents = await connection.manager
|
||||
.createQueryBuilder(Student, "students")
|
||||
// .orderBy("students.id")
|
||||
.getMany();
|
||||
|
||||
loadedStudents[0].should.have.all.keys("id", "name", "faculty");
|
||||
loadedStudents[0].id.should.equal(1);
|
||||
loadedStudents[0].name.should.equal("Alice");
|
||||
loadedStudents[0].faculty.should.equal("Economics");
|
||||
loadedStudents[1].should.have.all.keys("id", "name", "faculty");
|
||||
loadedStudents[1].id.should.equal(2);
|
||||
loadedStudents[1].name.should.equal("Bob");
|
||||
loadedStudents[1].faculty.should.equal("Programming");
|
||||
|
||||
let loadedTeachers = await connection.manager
|
||||
.createQueryBuilder(Teacher, "teachers")
|
||||
.getMany();
|
||||
|
||||
loadedTeachers[0].should.have.all.keys("id", "name", "specialization", "salary");
|
||||
loadedTeachers[0].id.should.equal(3);
|
||||
loadedTeachers[0].name.should.equal("Mr. Garrison");
|
||||
loadedTeachers[0].specialization.should.equal("Geography");
|
||||
loadedTeachers[0].salary.should.equal(2000);
|
||||
loadedTeachers[1].should.have.all.keys("id", "name", "specialization", "salary");
|
||||
loadedTeachers[1].id.should.equal(4);
|
||||
loadedTeachers[1].name.should.equal("Mr. Adler");
|
||||
loadedTeachers[1].specialization.should.equal("Mathematics");
|
||||
loadedTeachers[1].salary.should.equal(4000);
|
||||
|
||||
let loadedAccountants = await connection.manager
|
||||
.createQueryBuilder(Accountant, "accountants")
|
||||
.getMany();
|
||||
|
||||
loadedAccountants[0].should.have.all.keys("id", "name", "department", "salary");
|
||||
loadedAccountants[0].id.should.equal(5);
|
||||
loadedAccountants[0].name.should.equal("Mr. Burns");
|
||||
loadedAccountants[0].department.should.equal("Bookkeeping");
|
||||
loadedAccountants[0].salary.should.equal(3000);
|
||||
loadedAccountants[1].should.have.all.keys("id", "name", "department", "salary");
|
||||
loadedAccountants[1].id.should.equal(6);
|
||||
loadedAccountants[1].name.should.equal("Mr. Trump");
|
||||
loadedAccountants[1].department.should.equal("Director");
|
||||
loadedAccountants[1].salary.should.equal(5000);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Update
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
let loadedStudent = await connection.manager
|
||||
.createQueryBuilder(Student, "student")
|
||||
.where("student.name = :name", { name: "Bob" })
|
||||
.getOne();
|
||||
|
||||
console.log(loadedStudent);
|
||||
|
||||
loadedStudent!.faculty = "Chemistry";
|
||||
await connection.getRepository(Student).save(loadedStudent!);
|
||||
|
||||
loadedStudent = await connection.manager
|
||||
.createQueryBuilder(Student, "student")
|
||||
.where("student.name = :name", { name: "Bob" })
|
||||
.getOne();
|
||||
|
||||
loadedStudent!.should.have.all.keys("id", "name", "faculty");
|
||||
loadedStudent!.id.should.equal(2);
|
||||
loadedStudent!.name.should.equal("Bob");
|
||||
loadedStudent!.faculty.should.equal("Chemistry");
|
||||
|
||||
let loadedTeacher = await connection.manager
|
||||
.createQueryBuilder(Teacher, "teacher")
|
||||
.where("teacher.name = :name", { name: "Mr. Adler" })
|
||||
.getOne();
|
||||
|
||||
loadedTeacher!.salary = 1000;
|
||||
await connection.getRepository(Teacher).save(loadedTeacher!);
|
||||
|
||||
loadedTeacher = await connection.manager
|
||||
.createQueryBuilder(Teacher, "teacher")
|
||||
.where("teacher.name = :name", { name: "Mr. Adler" })
|
||||
.getOne();
|
||||
|
||||
loadedTeacher!.should.have.all.keys("id", "name", "specialization", "salary");
|
||||
loadedTeacher!.id.should.equal(4);
|
||||
loadedTeacher!.name.should.equal("Mr. Adler");
|
||||
loadedTeacher!.specialization.should.equal("Mathematics");
|
||||
loadedTeacher!.salary.should.equal(1000);
|
||||
|
||||
let loadedAccountant = await connection.manager
|
||||
.createQueryBuilder(Accountant, "accountant")
|
||||
.where("accountant.name = :name", { name: "Mr. Trump" })
|
||||
.getOne();
|
||||
|
||||
loadedAccountant!.salary = 1000;
|
||||
await connection.getRepository(Accountant).save(loadedAccountant!);
|
||||
|
||||
loadedAccountant = await connection.manager
|
||||
.createQueryBuilder(Accountant, "accountant")
|
||||
.where("accountant.name = :name", { name: "Mr. Trump" })
|
||||
.getOne();
|
||||
|
||||
loadedAccountant!.should.have.all.keys("id", "name", "department", "salary");
|
||||
loadedAccountant!.id.should.equal(6);
|
||||
loadedAccountant!.name.should.equal("Mr. Trump");
|
||||
loadedAccountant!.department.should.equal("Director");
|
||||
loadedAccountant!.salary.should.equal(1000);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Delete
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/*await connection.getRepository(Student).remove(loadedStudent!);
|
||||
|
||||
loadedStudents = await connection.manager
|
||||
.createQueryBuilder(Student, "students")
|
||||
.getMany();
|
||||
|
||||
loadedStudents.length.should.equal(1);
|
||||
loadedStudents[0].should.have.all.keys("id", "name", "faculty");
|
||||
loadedStudents[0].id.should.equal(1);
|
||||
loadedStudents[0].name.should.equal("Alice");
|
||||
loadedStudents[0].faculty.should.equal("Economics");
|
||||
|
||||
await connection.getRepository(Teacher).remove(loadedTeacher!);
|
||||
|
||||
loadedTeachers = await connection.manager
|
||||
.createQueryBuilder(Teacher, "teachers")
|
||||
.getMany();
|
||||
|
||||
loadedTeachers.length.should.equal(1);
|
||||
loadedTeachers[0].should.have.all.keys("id", "name", "specialization", "salary");
|
||||
loadedTeachers[0].id.should.equal(3);
|
||||
loadedTeachers[0].name.should.equal("Mr. Garrison");
|
||||
loadedTeachers[0].specialization.should.equal("Geography");
|
||||
loadedTeachers[0].salary.should.equal(2000);
|
||||
|
||||
await connection.getRepository(Accountant).remove(loadedAccountant!);
|
||||
|
||||
loadedAccountants = await connection.manager
|
||||
.createQueryBuilder(Accountant, "accountants")
|
||||
.getMany();
|
||||
|
||||
loadedAccountants.length.should.equal(1);
|
||||
loadedAccountants[0].should.have.all.keys("id", "name", "department", "salary");
|
||||
loadedAccountants[0].id.should.equal(5);
|
||||
loadedAccountants[0].name.should.equal("Mr. Burns");
|
||||
loadedAccountants[0].department.should.equal("Bookkeeping");
|
||||
loadedAccountants[0].salary.should.equal(3000);*/
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Select parent objects
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/*const loadedEmployees = await connection.manager
|
||||
.createQueryBuilder(Employee, "employees")
|
||||
.getMany();
|
||||
|
||||
loadedEmployees[0].should.have.all.keys("id", "name", "salary", "specialization");
|
||||
loadedEmployees[0].should.be.instanceof(Teacher);
|
||||
loadedEmployees[0].id.should.equal(3);
|
||||
loadedEmployees[0].name.should.equal("Mr. Garrison");
|
||||
(loadedEmployees[0] as Teacher).specialization = "Geography";
|
||||
loadedEmployees[0].salary.should.equal(2000);
|
||||
loadedEmployees[1].should.have.all.keys("id", "name", "salary", "department");
|
||||
loadedEmployees[1].should.be.instanceof(Accountant);
|
||||
loadedEmployees[1].id.should.equal(5);
|
||||
loadedEmployees[1].name.should.equal("Mr. Burns");
|
||||
(loadedEmployees[1] as Accountant).department = "Bookkeeping";
|
||||
loadedEmployees[1].salary.should.equal(3000);
|
||||
|
||||
const loadedPersons = await connection.manager
|
||||
.createQueryBuilder(Person, "persons")
|
||||
.getMany();
|
||||
|
||||
loadedPersons[0].should.have.all.keys("id", "name", "faculty");
|
||||
loadedPersons[0].should.be.instanceof(Student);
|
||||
loadedPersons[0].id.should.equal(1);
|
||||
loadedPersons[0].name.should.equal("Alice");
|
||||
(loadedPersons[0] as Student).faculty = "Economics";
|
||||
loadedPersons[1].should.have.all.keys("id", "name", "salary", "specialization");
|
||||
loadedPersons[1].should.be.instanceof(Teacher);
|
||||
loadedPersons[1].id.should.equal(3);
|
||||
loadedPersons[1].name.should.equal("Mr. Garrison");
|
||||
(loadedPersons[1] as Teacher).specialization = "Geography";
|
||||
(loadedPersons[1] as Teacher).salary.should.equal(2000);
|
||||
loadedPersons[2].should.have.all.keys("id", "name", "salary", "department");
|
||||
loadedPersons[2].should.be.instanceof(Accountant);
|
||||
loadedPersons[2].id.should.equal(5);
|
||||
loadedPersons[2].name.should.equal("Mr. Burns");
|
||||
(loadedPersons[2] as Accountant).department = "Bookkeeping";
|
||||
(loadedPersons[2] as Accountant).salary.should.equal(3000);*/
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -1,11 +0,0 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {ClassEntityChild} from "../../../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {Employee} from "./Employee";
|
||||
|
||||
@ClassEntityChild()
|
||||
export class Accountant extends Employee {
|
||||
|
||||
@Column()
|
||||
department: string;
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {ClassEntityChild} from "../../../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {Employee} from "./Employee";
|
||||
|
||||
@ClassEntityChild()
|
||||
export class Teacher extends Employee {
|
||||
|
||||
@Column()
|
||||
specialization: string;
|
||||
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {SingleEntityChild} from "../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {Employee} from "./Employee";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Accountant extends Employee {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {SingleEntityChild} from "../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {Person} from "./Person";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Employee extends Person {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {TableInheritance} from "../../../../../../src/decorator/entity/TableInheritance";
|
||||
import {DiscriminatorColumn} from "../../../../../../src/decorator/columns/DiscriminatorColumn";
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
|
||||
@Entity()
|
||||
@TableInheritance("single-table")
|
||||
@DiscriminatorColumn({ name: "type", type: "varchar" })
|
||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||
export class Person {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {SingleEntityChild} from "../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {Person} from "./Person";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Student extends Person {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {SingleEntityChild} from "../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {Employee} from "./Employee";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Teacher extends Employee {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {ClassEntityChild} from "../../../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {ChildEntity} from "../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {Person} from "./Person";
|
||||
|
||||
@ClassEntityChild()
|
||||
@ChildEntity("employee-type")
|
||||
export class Employee extends Person {
|
||||
|
||||
@Column()
|
||||
@ -1,12 +1,10 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {TableInheritance} from "../../../../../../src/decorator/entity/TableInheritance";
|
||||
import {DiscriminatorColumn} from "../../../../../../src/decorator/columns/DiscriminatorColumn";
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
|
||||
@Entity()
|
||||
@TableInheritance("class-table")
|
||||
@DiscriminatorColumn({ name: "type", type: "varchar" })
|
||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||
export class Person {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
@ -15,4 +13,7 @@ export class Person {
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
type: string;
|
||||
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {ClassEntityChild} from "../../../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {ChildEntity} from "../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {Person} from "./Person";
|
||||
|
||||
@ClassEntityChild()
|
||||
@ChildEntity("student-type")
|
||||
export class Student extends Person {
|
||||
|
||||
@Column()
|
||||
@ -0,0 +1,54 @@
|
||||
import "reflect-metadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {Student} from "./entity/Student";
|
||||
import {Employee} from "./entity/Employee";
|
||||
import {Person} from "./entity/Person";
|
||||
|
||||
describe("table-inheritance > single-table > non-virtual-discriminator-column", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"]
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should return non virtual discriminator column as well", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Create
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
const student = new Student();
|
||||
student.name = "Alice";
|
||||
student.faculty = "Economics";
|
||||
await connection.getRepository(Student).save(student);
|
||||
|
||||
const employee = new Employee();
|
||||
employee.name = "Roger";
|
||||
employee.salary = 1000;
|
||||
await connection.getRepository(Employee).save(employee);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Select
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
let persons = await connection.manager
|
||||
.createQueryBuilder(Person, "person")
|
||||
.getMany();
|
||||
|
||||
console.log(persons);
|
||||
|
||||
persons[0].id.should.be.equal(1);
|
||||
persons[0].type.should.be.equal("student-type");
|
||||
persons[0].name.should.be.equal("Alice");
|
||||
(persons[0] as Student).faculty.should.be.equal("Economics");
|
||||
|
||||
persons[1].id.should.be.equal(2);
|
||||
persons[1].type.should.be.equal("employee-type");
|
||||
persons[1].name.should.be.equal("Roger");
|
||||
(persons[1] as Employee).salary.should.be.equal(1000);
|
||||
})));
|
||||
|
||||
});
|
||||
@ -1,10 +1,10 @@
|
||||
import {SingleEntityChild} from "../../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Employee} from "./Employee";
|
||||
import {Department} from "./Department";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Accountant extends Employee {
|
||||
|
||||
@ManyToMany(type => Department, department => department.accountants)
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {SingleEntityChild} from "../../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {Person} from "./Person";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Employee extends Person {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {TableInheritance} from "../../../../../../../src/decorator/entity/TableInheritance";
|
||||
import {DiscriminatorColumn} from "../../../../../../../src/decorator/columns/DiscriminatorColumn";
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
|
||||
@Entity()
|
||||
@TableInheritance("single-table")
|
||||
@DiscriminatorColumn({ name: "type", type: "varchar" })
|
||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||
export class Person {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import {SingleEntityChild} from "../../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {Person} from "./Person";
|
||||
import {Faculty} from "./Faculty";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Student extends Person {
|
||||
|
||||
@ManyToMany(type => Faculty, faculty => faculty.students)
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import {SingleEntityChild} from "../../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Employee} from "./Employee";
|
||||
import {Specialization} from "./Specialization";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Teacher extends Employee {
|
||||
|
||||
@ManyToMany(type => Specialization, specialization => specialization.teachers)
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import {SingleEntityChild} from "../../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {OneToMany} from "../../../../../../../src/decorator/relations/OneToMany";
|
||||
import {Employee} from "./Employee";
|
||||
import {Department} from "./Department";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Accountant extends Employee {
|
||||
|
||||
@OneToMany(type => Department, department => department.accountant)
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {SingleEntityChild} from "../../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {Person} from "./Person";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Employee extends Person {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {TableInheritance} from "../../../../../../../src/decorator/entity/TableInheritance";
|
||||
import {DiscriminatorColumn} from "../../../../../../../src/decorator/columns/DiscriminatorColumn";
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
|
||||
@Entity()
|
||||
@TableInheritance("single-table")
|
||||
@DiscriminatorColumn({ name: "type", type: "varchar" })
|
||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||
export class Person {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import {SingleEntityChild} from "../../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {OneToMany} from "../../../../../../../src/decorator/relations/OneToMany";
|
||||
import {Person} from "./Person";
|
||||
import {Faculty} from "./Faculty";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Student extends Person {
|
||||
|
||||
@OneToMany(type => Faculty, faculty => faculty.student)
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import {SingleEntityChild} from "../../../../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity";
|
||||
import {OneToMany} from "../../../../../../../src/decorator/relations/OneToMany";
|
||||
import {Employee} from "./Employee";
|
||||
import {Specialization} from "./Specialization";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Teacher extends Employee {
|
||||
|
||||
@OneToMany(type => Specialization, specialization => specialization.teacher)
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
import {Person} from "./Person";
|
||||
import {SingleEntityChild} from "../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../src/decorator/entity/ChildEntity";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Employee extends Person {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
import {TableInheritance} from "../../../../src/decorator/entity/TableInheritance";
|
||||
import {DiscriminatorColumn} from "../../../../src/decorator/columns/DiscriminatorColumn";
|
||||
import {Entity} from "../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryColumn} from "../../../../src/decorator/columns/PrimaryColumn";
|
||||
|
||||
@Entity()
|
||||
@TableInheritance("single-table")
|
||||
@DiscriminatorColumn({ name: "type", type: "varchar" })
|
||||
@TableInheritance({ column: { name: "type", type: "varchar" } })
|
||||
export class Person {
|
||||
|
||||
@PrimaryColumn("int")
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
import {Person} from "./Person";
|
||||
import {SingleEntityChild} from "../../../../src/decorator/entity/SingleEntityChild";
|
||||
import {ChildEntity} from "../../../../src/decorator/entity/ChildEntity";
|
||||
|
||||
@SingleEntityChild()
|
||||
@ChildEntity()
|
||||
export class Student extends Person {
|
||||
|
||||
@Column()
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
import {Person} from "./Person";
|
||||
import {ClassEntityChild} from "../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
|
||||
@ClassEntityChild()
|
||||
export class Employee extends Person {
|
||||
|
||||
@Column()
|
||||
salary: number;
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
import {Person} from "./Person";
|
||||
import {ClassEntityChild} from "../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
|
||||
@ClassEntityChild()
|
||||
export class Homesitter extends Person {
|
||||
|
||||
@Column()
|
||||
numberOfKids: number;
|
||||
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import {Entity} from "../../../../src/decorator/entity/Entity";
|
||||
import {TableInheritance} from "../../../../src/decorator/entity/TableInheritance";
|
||||
import {DiscriminatorColumn} from "../../../../src/decorator/columns/DiscriminatorColumn";
|
||||
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
|
||||
@Entity()
|
||||
@TableInheritance("class-table")
|
||||
@DiscriminatorColumn({ name: "type", type: "varchar" })
|
||||
export class Person {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
firstName: string;
|
||||
|
||||
@Column()
|
||||
lastName: string;
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
import {Person} from "./Person";
|
||||
import {ClassEntityChild} from "../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
|
||||
@ClassEntityChild()
|
||||
export class Student extends Person {
|
||||
|
||||
@Column()
|
||||
faculty: string;
|
||||
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
import "reflect-metadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {Student} from "./entity/Student";
|
||||
|
||||
// todo fix this test once class table inheritance support is back
|
||||
describe.skip("github issues > #144 Class Table Inheritance doesn't seem to work", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should persist class table child successfully", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const studentRepository = connection.getRepository(Student);
|
||||
|
||||
const student = new Student();
|
||||
student.firstName = "Hello";
|
||||
student.lastName = "World";
|
||||
student.faculty = "University";
|
||||
|
||||
await studentRepository.save(student);
|
||||
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -1,24 +0,0 @@
|
||||
import {Entity} from "../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
import {OneToOne} from "../../../../src/decorator/relations/OneToOne";
|
||||
import {JoinColumn} from "../../../../src/decorator/relations/JoinColumn";
|
||||
import {Employee} from "./Employee";
|
||||
|
||||
@Entity()
|
||||
export class Department {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@OneToOne(type => Employee, {
|
||||
cascade: ["insert"],
|
||||
nullable: false
|
||||
})
|
||||
@JoinColumn()
|
||||
manager: Employee;
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
import {Person} from "./Person";
|
||||
import {ClassEntityChild} from "../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
|
||||
@ClassEntityChild()
|
||||
export class Employee extends Person {
|
||||
|
||||
@Column()
|
||||
salary: number;
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
import {Person} from "./Person";
|
||||
import {ClassEntityChild} from "../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
|
||||
@ClassEntityChild()
|
||||
export class Homesitter extends Person {
|
||||
|
||||
@Column()
|
||||
numberOfKids: number;
|
||||
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import {Entity} from "../../../../src/decorator/entity/Entity";
|
||||
import {TableInheritance} from "../../../../src/decorator/entity/TableInheritance";
|
||||
import {DiscriminatorColumn} from "../../../../src/decorator/columns/DiscriminatorColumn";
|
||||
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
|
||||
@Entity()
|
||||
@TableInheritance("class-table")
|
||||
@DiscriminatorColumn({ name: "type", type: "varchar" })
|
||||
export class Person {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
firstName: string;
|
||||
|
||||
@Column()
|
||||
lastName: string;
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
import {Person} from "./Person";
|
||||
import {ClassEntityChild} from "../../../../src/decorator/entity/ClassEntityChild";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
|
||||
@ClassEntityChild()
|
||||
export class Student extends Person {
|
||||
|
||||
@Column()
|
||||
faculty: string;
|
||||
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
import "reflect-metadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {Department} from "./entity/Department";
|
||||
import {Employee} from "./entity/Employee";
|
||||
|
||||
// unskip once table inheritance support is back
|
||||
describe.skip("github issues > #159 Referencing ClassTableChild build table error", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("entity should be successfully referenced to class-table entity", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
let department = new Department();
|
||||
department.name = "Software";
|
||||
|
||||
let employee = new Employee();
|
||||
employee.firstName = "Hello";
|
||||
employee.lastName = "World";
|
||||
employee.salary = 1;
|
||||
|
||||
department.manager = employee;
|
||||
|
||||
await connection.manager.save(department);
|
||||
|
||||
department.id.should.be.equal(1);
|
||||
department.name.should.be.equal("Software");
|
||||
department.manager.id.should.be.equal(1);
|
||||
department.manager.firstName.should.be.equal("Hello");
|
||||
department.manager.lastName.should.be.equal("World");
|
||||
department.manager.salary.should.be.equal(1);
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -1,11 +0,0 @@
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
import {Document} from "./Document";
|
||||
import {ClassEntityChild} from "../../../../src/decorator/entity/ClassEntityChild";
|
||||
|
||||
@ClassEntityChild()
|
||||
export class DeliveryNote extends Document {
|
||||
|
||||
@Column()
|
||||
invoice: string = "";
|
||||
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
import {Entity} from "../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
import {TableInheritance} from "../../../../src/decorator/entity/TableInheritance";
|
||||
import {CreateDateColumn} from "../../../../src/decorator/columns/CreateDateColumn";
|
||||
import {UpdateDateColumn} from "../../../../src/decorator/columns/UpdateDateColumn";
|
||||
|
||||
@Entity()
|
||||
@TableInheritance("class-table")
|
||||
export class Document {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
dollarRate: number = 0;
|
||||
|
||||
@Column()
|
||||
orderBy: string = "";
|
||||
|
||||
@Column()
|
||||
comments: string = "";
|
||||
|
||||
@Column()
|
||||
subTotal: number = 0;
|
||||
|
||||
@Column()
|
||||
vat: number = 0;
|
||||
|
||||
@Column()
|
||||
total: number = 0;
|
||||
|
||||
@Column()
|
||||
createdBy: string = "";
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: string;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: string;
|
||||
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
import "reflect-metadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {DeliveryNote} from "./entity/DeliveryNote";
|
||||
import {expect} from "chai";
|
||||
|
||||
// unskip when inheritance will repaired
|
||||
describe.skip("github issues > #78 repository 'create' is skipping inherited fields", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should persist successfully and return persisted entity", () => Promise.all(connections.map(async connection => {
|
||||
const repository = connection.getRepository(DeliveryNote);
|
||||
|
||||
const deliveryNoteEntity = repository.create({
|
||||
id: 1,
|
||||
dollarRate: 0.5,
|
||||
orderBy: "money",
|
||||
comments: "this is comment",
|
||||
subTotal: 10,
|
||||
vat: 50,
|
||||
total: 60,
|
||||
createdBy: "Amir",
|
||||
invoice: "Total Invoice: 60"
|
||||
});
|
||||
|
||||
expect(deliveryNoteEntity).not.to.be.empty;
|
||||
deliveryNoteEntity.should.be.instanceof(DeliveryNote);
|
||||
const simpleObject = Object.assign({}, deliveryNoteEntity);
|
||||
simpleObject.should.be.eql({
|
||||
dollarRate: 0.5,
|
||||
orderBy: "money",
|
||||
comments: "this is comment",
|
||||
subTotal: 10,
|
||||
vat: 50,
|
||||
total: 60,
|
||||
createdBy: "Amir",
|
||||
invoice: "Total Invoice: 60",
|
||||
id: 1
|
||||
});
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user