mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fixed all issues related to metadata args changes
This commit is contained in:
parent
c5228e4978
commit
290204f573
@ -350,7 +350,7 @@ export class Connection {
|
||||
getMetadataArgsStorage()
|
||||
.namingStrategyMetadatas
|
||||
.filterByClasses(this.namingStrategyClasses)
|
||||
.forEach(namingStrategy => this.namingStrategyMetadatas.push(namingStrategy));
|
||||
.forEach(metadata => this.namingStrategyMetadatas.push(new NamingStrategyMetadata(metadata)));
|
||||
|
||||
// take imported event subscribers
|
||||
getMetadataArgsStorage()
|
||||
@ -363,14 +363,14 @@ export class Connection {
|
||||
getMetadataArgsStorage()
|
||||
.entityListenerMetadatas
|
||||
.filterByClasses(this.entityClasses)
|
||||
.forEach(entityListener => this.entityListeners.push(entityListener));
|
||||
.forEach(metadata => this.entityListeners.push(new EntityListenerMetadata(metadata)));
|
||||
|
||||
// build entity metadatas for the current connection
|
||||
getFromContainer(EntityMetadataBuilder)
|
||||
.build(this.createNamingStrategy(), this.entityClasses)
|
||||
.forEach(metadata => {
|
||||
this.entityMetadatas.push(metadata);
|
||||
this.createRepository(metadata);
|
||||
.forEach(layout => {
|
||||
this.entityMetadatas.push(layout);
|
||||
this.createRepository(layout);
|
||||
});
|
||||
}
|
||||
|
||||
@ -391,15 +391,15 @@ export class Connection {
|
||||
/**
|
||||
* Creates repository and reactive repository for the given entity metadata.
|
||||
*/
|
||||
private createRepository(metadata: EntityMetadata) {
|
||||
private createRepository(entityLayout: EntityMetadata) {
|
||||
const repositoryFactory = getFromContainer(RepositoryFactory);
|
||||
if (metadata.table.isClosure) {
|
||||
const repository = repositoryFactory.createRepository(this, this.entityMetadatas, metadata);
|
||||
if (entityLayout.table.isClosure) {
|
||||
const repository = repositoryFactory.createRepository(this, this.entityMetadatas, entityLayout);
|
||||
const reactiveRepository = repositoryFactory.createReactiveRepository(repository);
|
||||
this.repositories.push(repository);
|
||||
this.reactiveRepositories.push(reactiveRepository);
|
||||
} else {
|
||||
const repository = repositoryFactory.createTreeRepository(this, this.entityMetadatas, metadata);
|
||||
const repository = repositoryFactory.createTreeRepository(this, this.entityMetadatas, entityLayout);
|
||||
const reactiveRepository = repositoryFactory.createReactiveTreeRepository(repository);
|
||||
this.repositories.push(repository);
|
||||
this.reactiveRepositories.push(reactiveRepository);
|
||||
|
||||
@ -13,6 +13,8 @@ import {JoinColumnOptions} from "../metadata/options/JoinColumnOptions";
|
||||
import {TableMetadata} from "../metadata/TableMetadata";
|
||||
import {ColumnTypes} from "../metadata/types/ColumnTypes";
|
||||
import {getMetadataArgsStorage} from "../index";
|
||||
import {RelationMetadata} from "../metadata/RelationMetadata";
|
||||
import {JoinTableMetadata} from "../metadata/JoinTableMetadata";
|
||||
|
||||
/**
|
||||
* Aggregates all metadata: table, column, relation into one collection grouped by tables for a given set of classes.
|
||||
@ -31,17 +33,6 @@ export class EntityMetadataBuilder {
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private mergeIndicesAndCompositeIndices(indices: PropertyMetadataCollection<IndexMetadata>,
|
||||
compositeIndices: TargetMetadataCollection<CompositeIndexMetadata>) {
|
||||
indices.forEach(index => {
|
||||
const compositeIndex = new CompositeIndexMetadata(index.target, index.name, [index.propertyName]);
|
||||
compositeIndex.namingStrategy = index.namingStrategy;
|
||||
compositeIndices.add(compositeIndex);
|
||||
});
|
||||
|
||||
// later need to check if no duplicate keys in composite indices?
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a complete metadata aggregations for the given entity classes.
|
||||
@ -53,7 +44,9 @@ export class EntityMetadataBuilder {
|
||||
|
||||
// filter the only metadata we need - those which are bind to the given table classes
|
||||
const allTableMetadatas = allMetadataStorage.tableMetadatas.filterByClasses(entityClasses);
|
||||
const tableMetadatas = allTableMetadatas.filterByClasses(entityClasses).filter(table => !table.isAbstract);
|
||||
const tableMetadatas = allTableMetadatas
|
||||
.filterByClasses(entityClasses)
|
||||
.filter(metadata => metadata.type !== "abstract");
|
||||
|
||||
// set naming strategy
|
||||
// allMetadataStorage.tableMetadatas.forEach(tableMetadata => tableMetadata.namingStrategy = namingStrategy);
|
||||
@ -64,15 +57,22 @@ export class EntityMetadataBuilder {
|
||||
|
||||
const mergedMetadata = allMetadataStorage.mergeWithAbstract(allTableMetadatas, tableMetadata);
|
||||
|
||||
// set naming strategy
|
||||
// tableMetadata.namingStrategy = namingStrategy;
|
||||
mergedMetadata.columnMetadatas.forEach(column => column.namingStrategy = namingStrategy);
|
||||
mergedMetadata.relationMetadatas.forEach(relation => relation.namingStrategy = namingStrategy);
|
||||
mergedMetadata.indexMetadatas.forEach(relation => relation.namingStrategy = namingStrategy);
|
||||
mergedMetadata.compositeIndexMetadatas.forEach(relation => relation.namingStrategy = namingStrategy);
|
||||
|
||||
// create layouts from metadatas
|
||||
const columns = mergedMetadata.columnMetadatas.map(metadata => new ColumnMetadata(metadata));
|
||||
const relations = mergedMetadata.relationMetadatas.map(metadata => new RelationMetadata(metadata));
|
||||
const compositeIndices = mergedMetadata.compositeIndexMetadatas.map(metadata => new CompositeIndexMetadata(metadata));
|
||||
|
||||
// merge indices and composite indices because simple indices actually are compose indices with only one column
|
||||
this.mergeIndicesAndCompositeIndices(mergedMetadata.indexMetadatas, mergedMetadata.compositeIndexMetadatas);
|
||||
// todo: no need to create index layout for this, use index metadata instead
|
||||
const indices = mergedMetadata.indexMetadatas.map(metadata => new IndexMetadata(metadata));
|
||||
const compositeFromSimpleIndices = this.createCompositeIndicesFromSimpleIndices(indices);
|
||||
compositeIndices.push(...compositeFromSimpleIndices);
|
||||
|
||||
// todo no need to set naming strategy everywhere - childs can obtain it from their parents
|
||||
// tableMetadata.namingStrategy = namingStrategy;
|
||||
columns.forEach(column => column.namingStrategy = namingStrategy);
|
||||
relations.forEach(relation => relation.namingStrategy = namingStrategy);
|
||||
compositeIndices.forEach(index => index.namingStrategy = namingStrategy);
|
||||
|
||||
// todo: check if multiple tree parent metadatas in validator
|
||||
// todo: tree decorators can be used only on closure table (validation)
|
||||
@ -81,16 +81,17 @@ export class EntityMetadataBuilder {
|
||||
// create a new entity metadata
|
||||
const entityMetadata = new EntityMetadata(
|
||||
namingStrategy,
|
||||
tableMetadata,
|
||||
mergedMetadata.columnMetadatas,
|
||||
mergedMetadata.relationMetadatas,
|
||||
mergedMetadata.compositeIndexMetadatas
|
||||
new TableMetadata(tableMetadata),
|
||||
columns,
|
||||
relations,
|
||||
compositeIndices
|
||||
);
|
||||
|
||||
// create entity's relations join tables
|
||||
entityMetadata.manyToManyRelations.forEach(relation => {
|
||||
const joinTable = mergedMetadata.joinTableMetadatas.findByProperty(relation.propertyName);
|
||||
if (joinTable) {
|
||||
const joinTableMetadata = mergedMetadata.joinTableMetadatas.findByProperty(relation.propertyName);
|
||||
if (joinTableMetadata) {
|
||||
const joinTable = new JoinTableMetadata(joinTableMetadata);
|
||||
relation.joinTable = joinTable;
|
||||
joinTable.relation = relation;
|
||||
}
|
||||
@ -98,8 +99,9 @@ export class EntityMetadataBuilder {
|
||||
|
||||
// create entity's relations join columns
|
||||
entityMetadata.relations.forEach(relation => {
|
||||
const joinColumn = mergedMetadata.joinColumnMetadatas.findByProperty(relation.propertyName);
|
||||
if (joinColumn) {
|
||||
const joinColumnMetadata = mergedMetadata.joinColumnMetadatas.findByProperty(relation.propertyName);
|
||||
if (joinColumnMetadata) {
|
||||
const joinColumn = new JoinColumnMetadata(joinColumnMetadata);
|
||||
relation.joinColumn = joinColumn;
|
||||
joinColumn.relation = relation;
|
||||
}
|
||||
@ -108,9 +110,10 @@ export class EntityMetadataBuilder {
|
||||
// since for many-to-one relations having JoinColumn is not required on decorators level, we need to go
|
||||
// throw all of them which don't have JoinColumn decorators and create it for them
|
||||
entityMetadata.manyToOneRelations.forEach(relation => {
|
||||
let joinColumn = mergedMetadata.joinColumnMetadatas.findByProperty(relation.propertyName);
|
||||
if (!joinColumn) {
|
||||
joinColumn = new JoinColumnMetadata(relation.target, relation.propertyName, <JoinColumnOptions> {});
|
||||
let joinColumnMetadata = mergedMetadata.joinColumnMetadatas.findByProperty(relation.propertyName);
|
||||
if (!joinColumnMetadata) {
|
||||
joinColumnMetadata = { target: relation.target, propertyName: relation.propertyName, options: <JoinColumnOptions> {} };
|
||||
const joinColumn = new JoinColumnMetadata(joinColumnMetadata);
|
||||
relation.joinColumn = joinColumn;
|
||||
joinColumn.relation = relation;
|
||||
}
|
||||
@ -179,16 +182,20 @@ export class EntityMetadataBuilder {
|
||||
|
||||
const columns = [
|
||||
new ColumnMetadata({
|
||||
target: Function, // todo: temp, fix it later
|
||||
propertyName: "", // todo: temp, fix it later
|
||||
propertyType: metadata.primaryColumn.type,
|
||||
options: {
|
||||
options: <ColumnOptions> {
|
||||
length: metadata.primaryColumn.length,
|
||||
type: metadata.primaryColumn.type,
|
||||
name: "ancestor"
|
||||
}
|
||||
}),
|
||||
new ColumnMetadata({
|
||||
target: Function, // todo: temp, fix it later
|
||||
propertyName: "", // todo: temp, fix it later
|
||||
propertyType: metadata.primaryColumn.type,
|
||||
options: {
|
||||
options: <ColumnOptions> {
|
||||
length: metadata.primaryColumn.length,
|
||||
type: metadata.primaryColumn.type,
|
||||
name: "descendant"
|
||||
@ -198,6 +205,8 @@ export class EntityMetadataBuilder {
|
||||
|
||||
if (metadata.hasTreeLevelColumn) {
|
||||
columns.push(new ColumnMetadata({
|
||||
target: Function, // todo: temp, fix it later
|
||||
propertyName: "", // todo: temp, fix it later
|
||||
propertyType: ColumnTypes.INTEGER,
|
||||
options: {
|
||||
type: ColumnTypes.INTEGER,
|
||||
@ -220,7 +229,11 @@ export class EntityMetadataBuilder {
|
||||
const junctionEntityMetadatas: EntityMetadata[] = [];
|
||||
entityMetadatas.forEach(metadata => {
|
||||
metadata.ownerManyToManyRelations.map(relation => {
|
||||
const tableMetadata = new TableMetadata(undefined, relation.joinTable.name, "junction");
|
||||
const tableMetadata = new TableMetadata({
|
||||
target: Function,
|
||||
name: relation.joinTable.name,
|
||||
type: "junction"
|
||||
});
|
||||
const column1 = relation.joinTable.referencedColumn;
|
||||
const column2 = relation.joinTable.inverseReferencedColumn;
|
||||
|
||||
@ -236,10 +249,14 @@ export class EntityMetadataBuilder {
|
||||
};
|
||||
const columns = [
|
||||
new ColumnMetadata({
|
||||
target: Function, // todo: temp, fix it later
|
||||
propertyName: "", // todo: temp, fix it later
|
||||
propertyType: column2.type,
|
||||
options: column1options
|
||||
}),
|
||||
new ColumnMetadata({
|
||||
target: Function, // todo: temp, fix it later
|
||||
propertyName: "", // todo: temp, fix it later
|
||||
propertyType: column2.type,
|
||||
options: column2options
|
||||
})
|
||||
@ -261,4 +278,20 @@ export class EntityMetadataBuilder {
|
||||
.concat(closureJunctionEntityMetadatas);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private createCompositeIndicesFromSimpleIndices(indices: IndexMetadata[]) {
|
||||
return indices.map(index => {
|
||||
return new CompositeIndexMetadata({
|
||||
name: index.name,
|
||||
target: index.target,
|
||||
columns: [index.propertyName]
|
||||
});
|
||||
});
|
||||
|
||||
// later need to check if no duplicate keys in composite indices?
|
||||
}
|
||||
|
||||
}
|
||||
@ -22,6 +22,7 @@ import {NamingStrategyMetadataArgs} from "../metadata/args/NamingStrategyMetadat
|
||||
import {EventSubscriberMetadataArgs} from "../metadata/args/EventSubscriberMetadataArgs";
|
||||
import {JoinTableMetadataArgs} from "../metadata/args/JoinTableMetadataArgs";
|
||||
import {JoinColumnMetadataArgs} from "../metadata/args/JoinColumnMetadataArgs";
|
||||
import {TargetMetadataArgs} from "../metadata/args/TargetMetadataArgs";
|
||||
|
||||
/**
|
||||
* Storage all metadatas of all available types: tables, fields, subscribers, relations, etc.
|
||||
@ -65,8 +66,8 @@ export class MetadataArgsStorage {
|
||||
* Creates a new copy of the MetadataStorage with same metadatas as in current metadata storage, but filtered
|
||||
* by classes.
|
||||
*/
|
||||
mergeWithAbstract(allTableMetadatas: TargetMetadataCollection<TableMetadata>,
|
||||
tableMetadata: TableMetadata) {
|
||||
mergeWithAbstract(allTableMetadatas: TargetMetadataCollection<TableMetadataArgs>,
|
||||
tableMetadata: TableMetadataArgs) {
|
||||
|
||||
const compositeIndexMetadatas = this.compositeIndexMetadatas.filterByClass(tableMetadata.target);
|
||||
const columnMetadatas = this.columnMetadatas.filterByClass(tableMetadata.target);
|
||||
@ -78,7 +79,7 @@ export class MetadataArgsStorage {
|
||||
const relationCountMetadatas = this.relationCountMetadatas.filterByClass(tableMetadata.target);
|
||||
|
||||
allTableMetadatas
|
||||
.filter(metadata => tableMetadata.isInherited(metadata))
|
||||
.filter(metadata => this.isInherited(tableMetadata, metadata))
|
||||
.forEach(parentMetadata => {
|
||||
const metadatasFromAbstract = this.mergeWithAbstract(allTableMetadatas, parentMetadata);
|
||||
|
||||
@ -122,5 +123,16 @@ export class MetadataArgsStorage {
|
||||
relationCountMetadatas: relationCountMetadatas
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if this table is inherited from another table.
|
||||
*/
|
||||
private isInherited(firstTargetMetadata: TargetMetadataArgs, secondTargetMetadata: TargetMetadataArgs) {
|
||||
return Object.getPrototypeOf(firstTargetMetadata.target.prototype).constructor === secondTargetMetadata.target;
|
||||
// we cannot use instanceOf in this method, because we need order of inherited tables, to ensure that
|
||||
// properties get inherited in a right order. To achieve it we can only check a first parent of the class
|
||||
// return this.target.prototype instanceof anotherTable.target;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -169,13 +169,6 @@ export class RelationMetadata extends PropertyMetadata {
|
||||
return this.namingStrategy ? this.namingStrategy.relationName(this.propertyName) : this.propertyName;
|
||||
}
|
||||
|
||||
get referencedColumnName(): string {
|
||||
if (this.joinColumn && this.joinColumn.referencedColumn && this.joinColumn.referencedColumn.name)
|
||||
return this.joinColumn.referencedColumn.name;
|
||||
|
||||
return this.inverseEntityMetadata.primaryColumn.propertyName;
|
||||
}
|
||||
|
||||
get referencedColumnName(): string {
|
||||
if (this.joinColumn && this.joinColumn.referencedColumn && this.joinColumn.referencedColumn.name)
|
||||
return this.joinColumn.referencedColumn.name;
|
||||
|
||||
@ -39,12 +39,23 @@ export class TableMetadata extends TargetMetadata {
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(metadata: TableMetadataArgs) {
|
||||
super(metadata.target);
|
||||
|
||||
this.tableType = metadata.type;
|
||||
if (metadata.name)
|
||||
this._name = name;
|
||||
constructor(target: Function|undefined, name: string, type: TableType);
|
||||
constructor(metadata: TableMetadataArgs);
|
||||
constructor(metadataOrTarget: TableMetadataArgs|Function|undefined, name?: string, type?: TableType) {
|
||||
if (arguments.length === 1) {
|
||||
const metadata = metadataOrTarget as TableMetadataArgs;
|
||||
super(metadata.target);
|
||||
this.tableType = metadata.type;
|
||||
if (metadata.name)
|
||||
this._name = metadata.name;
|
||||
|
||||
} else {
|
||||
super(metadataOrTarget as Function);
|
||||
if (name)
|
||||
this._name = name;
|
||||
if (type)
|
||||
this.tableType = type;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
@ -81,19 +92,4 @@ export class TableMetadata extends TargetMetadata {
|
||||
|
||||
return this.entityMetadata.namingStrategy.tableName((<any>this.target).name);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks if this table is inherited from another table.
|
||||
*/
|
||||
isInherited(anotherTable: TableMetadata) {
|
||||
return Object.getPrototypeOf(this.target.prototype).constructor === anotherTable.target;
|
||||
// we cannot use instanceOf in this method, because we need order of inherited tables, to ensure that
|
||||
// properties get inherited in a right order. To achieve it we can only check a first parent of the class
|
||||
// return this.target.prototype instanceof anotherTable.target;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
import {CompositeIndexOptions} from "../options/CompositeIndexOptions";
|
||||
import {TargetMetadataArgs} from "./TargetMetadataArgs";
|
||||
|
||||
/**
|
||||
*/
|
||||
export interface CompositeIndexMetadataArgs {
|
||||
export interface CompositeIndexMetadataArgs extends TargetMetadataArgs {
|
||||
|
||||
/**
|
||||
* Class to which this column is applied.
|
||||
*/
|
||||
target: Function;
|
||||
|
||||
name: string|undefined,
|
||||
name?: string;
|
||||
|
||||
columns: ((object: any) => any[])|string[],
|
||||
columns: ((object: any) => any[])|string[];
|
||||
|
||||
options?: CompositeIndexOptions;
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import {TargetMetadataArgs} from "./TargetMetadataArgs";
|
||||
|
||||
/**
|
||||
*/
|
||||
export interface EventSubscriberMetadataArgs {
|
||||
export interface EventSubscriberMetadataArgs extends TargetMetadataArgs {
|
||||
|
||||
/**
|
||||
* Class to which this subscriber is applied.
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import {TargetMetadataArgs} from "./TargetMetadataArgs";
|
||||
|
||||
/**
|
||||
*/
|
||||
export interface NamingStrategyMetadataArgs {
|
||||
|
||||
/**
|
||||
*/
|
||||
target: Function;
|
||||
export interface NamingStrategyMetadataArgs extends TargetMetadataArgs {
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Constructor arguments for ColumnMetadata class.
|
||||
*/
|
||||
export interface ColumnMetadataArgs {
|
||||
export interface TargetMetadataArgs {
|
||||
|
||||
/**
|
||||
* Class to which this column is applied.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {MetadataAlreadyExistsError} from "../../metadata-storage/error/MetadataAlreadyExistsError";
|
||||
import {TableMetadataArgs} from "../args/TableMetadataArgs";
|
||||
import {TargetMetadataArgs} from "../args/TargetMetadataArgs";
|
||||
|
||||
export class TargetMetadataCollection<T extends TableMetadataArgs> extends Array<T> {
|
||||
export class TargetMetadataCollection<T extends TargetMetadataArgs> extends Array<T> {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
|
||||
@ -633,10 +633,10 @@ export class QueryBuilder<Entity> {
|
||||
const metadata = this.aliasMap.getEntityMetadataByAlias(alias);
|
||||
if (!metadata) return;
|
||||
metadata.columns.forEach(column => {
|
||||
statement = statement.replace(new RegExp(alias.name + "." + column.propertyName, 'g'), alias.name + "." + column.name);
|
||||
statement = statement.replace(new RegExp(alias.name + "." + column.propertyName, "g"), alias.name + "." + column.name);
|
||||
});
|
||||
metadata.relations.forEach(relation => {
|
||||
statement = statement.replace(new RegExp(alias.name + "." + relation.propertyName, 'g'), alias.name + "." + relation.name);
|
||||
statement = statement.replace(new RegExp(alias.name + "." + relation.propertyName, "g"), alias.name + "." + relation.name);
|
||||
});
|
||||
});
|
||||
return statement;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user