From d401b4f3edbf50f339110f1de93bbde01e5d46ff Mon Sep 17 00:00:00 2001 From: Zotov Dmitry Date: Tue, 2 May 2017 12:17:09 +0500 Subject: [PATCH] removed table metadata --- src/driver/mongodb/MongoDriver.ts | 2 +- src/lazy-loading/LazyRelationsWrapper.ts | 2 +- src/metadata-args/EntityMetadataArgs.ts | 9 +- .../ClosureJunctionEntityMetadataBuilder.ts | 16 +- src/metadata-builder/EntityMetadataBuilder.ts | 98 +++------ .../EntityMetadataValidator.ts | 2 +- src/metadata/EmbeddedMetadata.ts | 10 +- src/metadata/EntityMetadata.ts | 140 +++++++++++- src/metadata/ForeignKeyMetadata.ts | 21 +- src/metadata/IndexMetadata.ts | 4 +- src/metadata/RelationMetadata.ts | 6 +- src/metadata/TableMetadata.ts | 205 ------------------ .../error/EntityMetadataAlreadySetError.ts | 14 -- .../error/EntityMetadataNotSetError.ts | 15 -- src/persistence/SubjectBuilder.ts | 6 +- src/persistence/SubjectOperationExecutor.ts | 60 ++--- src/query-builder/JoinAttribute.ts | 4 +- src/query-builder/QueryBuilder.ts | 16 +- .../relation-count/RelationCountLoader.ts | 8 +- .../relation-id/RelationIdLoader.ts | 8 +- src/repository/MongoRepository.ts | 106 ++++----- src/repository/Repository.ts | 14 +- src/repository/RepositoryAggregator.ts | 2 +- src/repository/SpecificRepository.ts | 22 +- src/repository/TreeRepository.ts | 4 +- src/schema-builder/SchemaBuilder.ts | 34 +-- src/schema-builder/schema/IndexSchema.ts | 2 +- src/schema-builder/schema/TableSchema.ts | 2 +- test/functional/connection/connection.ts | 6 +- 29 files changed, 336 insertions(+), 502 deletions(-) delete mode 100644 src/metadata/TableMetadata.ts delete mode 100644 src/metadata/error/EntityMetadataAlreadySetError.ts delete mode 100644 src/metadata/error/EntityMetadataNotSetError.ts diff --git a/src/driver/mongodb/MongoDriver.ts b/src/driver/mongodb/MongoDriver.ts index a1ef21d2d..3416e467b 100644 --- a/src/driver/mongodb/MongoDriver.ts +++ b/src/driver/mongodb/MongoDriver.ts @@ -225,7 +225,7 @@ export class MongoDriver implements Driver { metadata.indices.forEach(index => { const columns = index.buildColumnsAsMap(1); const options = { name: index.name }; - promises.push(queryRunner.createCollectionIndex(metadata.table.name, columns, options)); + promises.push(queryRunner.createCollectionIndex(metadata.tableName, columns, options)); }); })); await Promise.all(promises); diff --git a/src/lazy-loading/LazyRelationsWrapper.ts b/src/lazy-loading/LazyRelationsWrapper.ts index 0b5f4db02..b17f1b079 100644 --- a/src/lazy-loading/LazyRelationsWrapper.ts +++ b/src/lazy-loading/LazyRelationsWrapper.ts @@ -94,7 +94,7 @@ export class LazyRelationsWrapper { } else { // ManyToMany const mainAlias = relation.propertyName; - const joinAlias = relation.junctionEntityMetadata.table.name; + const joinAlias = relation.junctionEntityMetadata.tableName; let joinColumnConditions: string[] = []; let inverseJoinColumnConditions: string[] = []; let parameters: ObjectLiteral; diff --git a/src/metadata-args/EntityMetadataArgs.ts b/src/metadata-args/EntityMetadataArgs.ts index d32a740dc..b6ecd9251 100644 --- a/src/metadata-args/EntityMetadataArgs.ts +++ b/src/metadata-args/EntityMetadataArgs.ts @@ -1,12 +1,13 @@ import {ColumnMetadata} from "../metadata/ColumnMetadata"; import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface"; -import {TableMetadata} from "../metadata/TableMetadata"; import {RelationMetadata} from "../metadata/RelationMetadata"; import {IndexMetadata} from "../metadata/IndexMetadata"; import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata"; import {EmbeddedMetadata} from "../metadata/EmbeddedMetadata"; import {RelationIdMetadata} from "../metadata/RelationIdMetadata"; import {RelationCountMetadata} from "../metadata/RelationCountMetadata"; +import {OrderByCondition} from "../find-options/OrderByCondition"; +import {TableType} from "../metadata/types/TableTypes"; /** * Arguments for EntityMetadata class. @@ -16,10 +17,11 @@ export interface EntityMetadataArgs { readonly junction: boolean; readonly target: Function|string; readonly tablesPrefix?: string; + readonly tableName?: string; + readonly tableType: TableType; readonly inheritanceType?: "single-table"|"class-table"; readonly discriminatorValue?: string; readonly namingStrategy: NamingStrategyInterface; - readonly tableMetadata: TableMetadata; readonly columnMetadatas?: ColumnMetadata[]; readonly relationMetadatas?: RelationMetadata[]; readonly relationIdMetadatas?: RelationIdMetadata[]; @@ -27,5 +29,8 @@ export interface EntityMetadataArgs { readonly indexMetadatas?: IndexMetadata[]; readonly foreignKeyMetadatas?: ForeignKeyMetadata[]; readonly embeddedMetadatas?: EmbeddedMetadata[]; + readonly engine?: string; + readonly skipSchemaSync?: boolean; + readonly orderBy?: OrderByCondition|((object: any) => OrderByCondition|any); } diff --git a/src/metadata-builder/ClosureJunctionEntityMetadataBuilder.ts b/src/metadata-builder/ClosureJunctionEntityMetadataBuilder.ts index 4b8a26fee..4301aa105 100644 --- a/src/metadata-builder/ClosureJunctionEntityMetadataBuilder.ts +++ b/src/metadata-builder/ClosureJunctionEntityMetadataBuilder.ts @@ -3,7 +3,6 @@ import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterfac import {ColumnMetadata} from "../metadata/ColumnMetadata"; import {ColumnOptions} from "../decorator/options/ColumnOptions"; import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata"; -import {TableMetadata} from "../metadata/TableMetadata"; import {ColumnMetadataArgs} from "../metadata-args/ColumnMetadataArgs"; import {ColumnTypes} from "../metadata/types/ColumnTypes"; import {LazyRelationsWrapper} from "../lazy-loading/LazyRelationsWrapper"; @@ -14,7 +13,7 @@ import {Driver} from "../driver/Driver"; */ export interface ClosureJunctionEntityMetadataBuilderArgs { namingStrategy: NamingStrategyInterface; - table: TableMetadata; + entityMetadata: EntityMetadata; primaryColumn: ColumnMetadata; hasTreeLevelColumn: boolean; } @@ -64,22 +63,17 @@ export class ClosureJunctionEntityMetadataBuilder { })); } - const closureJunctionTableMetadata = new TableMetadata({ - target: "__virtual__", - name: args.table.name, - type: "closure-junction" - }); - return new EntityMetadata({ junction: true, target: "__virtual__", tablesPrefix: driver.options.tablesPrefix, namingStrategy: args.namingStrategy, - tableMetadata: closureJunctionTableMetadata, + tableName: args.entityMetadata.tableName, + tableType: "closure-junction", columnMetadatas: columns, foreignKeyMetadatas: [ - new ForeignKeyMetadata([columns[0]], args.table, [args.primaryColumn]), - new ForeignKeyMetadata([columns[1]], args.table, [args.primaryColumn]) + new ForeignKeyMetadata([columns[0]], args.entityMetadata, [args.primaryColumn]), + new ForeignKeyMetadata([columns[1]], args.entityMetadata, [args.primaryColumn]) ] }, lazyRelationsWrapper); } diff --git a/src/metadata-builder/EntityMetadataBuilder.ts b/src/metadata-builder/EntityMetadataBuilder.ts index ee9c1b454..11b2e9892 100644 --- a/src/metadata-builder/EntityMetadataBuilder.ts +++ b/src/metadata-builder/EntityMetadataBuilder.ts @@ -6,7 +6,6 @@ import {ColumnOptions} from "../decorator/options/ColumnOptions"; import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata"; import {EntityMetadataValidator} from "./EntityMetadataValidator"; import {IndexMetadata} from "../metadata/IndexMetadata"; -import {TableMetadata} from "../metadata/TableMetadata"; import {RelationMetadata} from "../metadata/RelationMetadata"; import {ClosureJunctionEntityMetadataBuilder} from "./ClosureJunctionEntityMetadataBuilder"; import {EmbeddedMetadata} from "../metadata/EmbeddedMetadata"; @@ -37,10 +36,10 @@ export class EntityMetadataBuilder { * Builds a complete metadata aggregations for the given entity classes. */ build(driver: Driver, - lazyRelationsWrapper: LazyRelationsWrapper, - metadataArgsStorage: MetadataArgsStorage, - namingStrategy: NamingStrategyInterface, - entityClasses?: Function[]): EntityMetadata[] { + lazyRelationsWrapper: LazyRelationsWrapper, + metadataArgsStorage: MetadataArgsStorage, + namingStrategy: NamingStrategyInterface, + entityClasses?: Function[]): EntityMetadata[] { const embeddableMergedArgs = metadataArgsStorage.getMergedEmbeddableTableMetadatas(entityClasses); const entityMetadatas: EntityMetadata[] = []; const allMergedArgs = metadataArgsStorage.getMergedTableMetadatas(entityClasses); @@ -55,10 +54,9 @@ export class EntityMetadataBuilder { embeddedArgs.forEach(embedded => { const embeddableTable = embeddableMergedArgs.find(embeddedMergedArgs => embeddedMergedArgs.table.target === embedded.type()); if (embeddableTable) { - const table = new TableMetadata(embeddableTable.table); const columns = embeddableTable.columns.toArray().map(args => new ColumnMetadata(args)); const subEmbeddeds = findEmbeddedsRecursively(embeddableTable.embeddeds.toArray()); - embeddeds.push(new EmbeddedMetadata(table, columns, subEmbeddeds, embedded)); + embeddeds.push(new EmbeddedMetadata(columns, subEmbeddeds, embedded)); } }); return embeddeds; @@ -68,7 +66,7 @@ export class EntityMetadataBuilder { // create metadatas from args const argsForTable = mergedArgs.inheritance && mergedArgs.inheritance.type === "single-table" ? mergedArgs.table : tableArgs; - const table = new TableMetadata(argsForTable); + // 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 @@ -92,7 +90,11 @@ export class EntityMetadataBuilder { target: tableArgs.target, tablesPrefix: driver.options.tablesPrefix, namingStrategy: namingStrategy, - tableMetadata: table, + tableName: argsForTable.name, + tableType: argsForTable.type, + orderBy: argsForTable.orderBy, + engine: argsForTable.engine, + skipSchemaSync: argsForTable.skipSchemaSync, columnMetadatas: columns, relationMetadatas: relations, relationIdMetadatas: relationIds, @@ -133,7 +135,7 @@ export class EntityMetadataBuilder { return mergedArgs.table.target === entityMetadata.target; }); if (mergedArgs && mergedArgs.parent) { - const parentEntityMetadata = entityMetadatas.find(entityMetadata => entityMetadata.table.target === (mergedArgs!.parent! as any).target); // todo: weird compiler error here, thats why type casing is used + 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; } @@ -144,9 +146,9 @@ export class EntityMetadataBuilder { .filter(metadata => !!metadata.parentEntityMetadata) .forEach(metadata => { const parentEntityMetadataPrimaryColumn = metadata.parentEntityMetadata.firstPrimaryColumn; // todo: make sure to create columns for all its primary columns - const columnName = namingStrategy.classTableInheritanceParentColumnName(metadata.parentEntityMetadata.table.name, parentEntityMetadataPrimaryColumn.propertyName); + const columnName = namingStrategy.classTableInheritanceParentColumnName(metadata.parentEntityMetadata.tableName, parentEntityMetadataPrimaryColumn.propertyName); const parentRelationColumn = new ColumnMetadata({ - target: metadata.parentEntityMetadata.table.target, + target: metadata.parentEntityMetadata.target, propertyName: parentEntityMetadataPrimaryColumn.propertyName, // propertyType: parentEntityMetadataPrimaryColumn.propertyType, mode: "parentId", @@ -165,7 +167,7 @@ export class EntityMetadataBuilder { // add foreign key const foreignKey = new ForeignKeyMetadata( [parentRelationColumn], - metadata.parentEntityMetadata.table, + metadata.parentEntityMetadata, [parentEntityMetadataPrimaryColumn], "CASCADE" ); @@ -260,7 +262,7 @@ export class EntityMetadataBuilder { const foreignKey = new ForeignKeyMetadata( columns, - relation.inverseEntityMetadata.table, + relation.inverseEntityMetadata, referencedColumns, relation.onDelete ); @@ -283,8 +285,8 @@ export class EntityMetadataBuilder { if (!joinTableMetadataArgs) return; const joinTableName = joinTableMetadataArgs.name || relation.entityMetadata.namingStrategy.joinTableName( - relation.entityMetadata.table.nameWithoutPrefix, - relation.inverseEntityMetadata.table.nameWithoutPrefix, + relation.entityMetadata.tableNameWithoutPrefix, + relation.inverseEntityMetadata.tableNameWithoutPrefix, relation.propertyName, relation.hasInverseSide ? relation.inverseRelation.propertyName : "" ); @@ -350,18 +352,12 @@ export class EntityMetadataBuilder { // (columnName => namingStrategy.joinTableColumnName(relation.inverseEntityMetadata.table.nameWithoutPrefix, columnName)) // ); - const tableMetadata = new TableMetadata({ - target: "", - name: joinTableName, - type: "junction" - }); - const junctionColumns = referencedColumns.map(referencedColumn => { const joinColumn = joinTableMetadataArgs.joinColumns ? joinTableMetadataArgs.joinColumns.find(joinColumnArgs => { return (!joinColumnArgs.referencedColumnName || joinColumnArgs.referencedColumnName === referencedColumn.propertyName) && !!joinColumnArgs.name; }) : undefined; - const columnName = joinColumn && joinColumn.name ? joinColumn.name : namingStrategy.joinTableColumnName(relation.entityMetadata.table.nameWithoutPrefix, referencedColumn.fullName); + const columnName = joinColumn && joinColumn.name ? joinColumn.name : namingStrategy.joinTableColumnName(relation.entityMetadata.tableNameWithoutPrefix, referencedColumn.fullName); return new ColumnMetadata({ target: "__virtual__", @@ -382,7 +378,7 @@ export class EntityMetadataBuilder { return (!joinColumnArgs.referencedColumnName || joinColumnArgs.referencedColumnName === inverseReferencedColumn.propertyName) && !!joinColumnArgs.name; }) : undefined; - const columnName = joinColumn && joinColumn.name ? joinColumn.name : namingStrategy.joinTableColumnName(relation.inverseEntityMetadata.table.nameWithoutPrefix, inverseReferencedColumn.fullName); + const columnName = joinColumn && joinColumn.name ? joinColumn.name : namingStrategy.joinTableColumnName(relation.inverseEntityMetadata.tableNameWithoutPrefix, inverseReferencedColumn.fullName); return new ColumnMetadata({ target: "__virtual__", @@ -399,8 +395,8 @@ export class EntityMetadataBuilder { }); const foreignKeys = [ - new ForeignKeyMetadata(junctionColumns, relation.entityMetadata.table, referencedColumns), - new ForeignKeyMetadata(inverseJunctionColumns, relation.inverseEntityMetadata.table, inverseReferencedColumns) + new ForeignKeyMetadata(junctionColumns, relation.entityMetadata, referencedColumns), + new ForeignKeyMetadata(inverseJunctionColumns, relation.inverseEntityMetadata, inverseReferencedColumns) ]; junctionColumns.concat(inverseJunctionColumns).forEach(column => column.relationMetadata = relation); @@ -410,7 +406,8 @@ export class EntityMetadataBuilder { target: "__virtual__", tablesPrefix: driver.options.tablesPrefix, namingStrategy: namingStrategy, - tableMetadata: tableMetadata, + tableName: joinTableName, + tableType: "junction", columnMetadatas: junctionColumns.concat(inverseJunctionColumns), foreignKeyMetadatas: foreignKeys, indexMetadatas: [ // todo: shall we remove indices? @@ -499,7 +496,7 @@ export class EntityMetadataBuilder { // generate junction tables for all closure tables entityMetadatas.forEach(metadata => { - if (!metadata.table.isClosure) + if (!metadata.isClosure) return; if (metadata.primaryColumns.length > 1) @@ -507,7 +504,7 @@ export class EntityMetadataBuilder { const closureJunctionEntityMetadata = getFromContainer(ClosureJunctionEntityMetadataBuilder).build(driver, lazyRelationsWrapper, { namingStrategy: namingStrategy, - table: metadata.table, + entityMetadata: metadata, primaryColumn: metadata.firstPrimaryColumn, hasTreeLevelColumn: metadata.hasTreeLevelColumn }); @@ -525,47 +522,4 @@ export class EntityMetadataBuilder { // Private Methods // ------------------------------------------------------------------------- - /*private createJoinColumns(joinColumnArgsArray: JoinColumnMetadataArgs[], - primaryColumns: ColumnMetadata[], - columnMetadatas: ColumnMetadata[], - relation: RelationMetadata, - columnNameFactory: (columnName: string) => string): ColumnMetadata[] { - - const hasAnyReferencedColumnName = joinColumnArgsArray.find(joinColumnArgs => !!joinColumnArgs.referencedColumnName); - const createColumns = (joinColumnArgsArray.length === 0 && relation.isManyToOne) || - (joinColumnArgsArray.length > 0 && !hasAnyReferencedColumnName) || - (relation.isManyToMany && !hasAnyReferencedColumnName); - - if (createColumns) { // covers case3 and case1 - - joinColumnArgsArray = primaryColumns.map(primaryColumn => { - - // in the case if relation has join column with only name set we need this check - const joinColumnMetadataArg = joinColumnArgsArray.find(joinColumnArgs => !joinColumnArgs.referencedColumnName && !!joinColumnArgs.name); - return { - target: relation.entityMetadata.target, - propertyName: relation.propertyName, - referencedColumnName: primaryColumn.propertyName, - name: joinColumnMetadataArg ? joinColumnMetadataArg.name : undefined - }; - }); - } - - return joinColumnArgsArray.map(joinColumnMetadataArgs => { - const joinColumn = new JoinColumnMetadata(); - joinColumn.relation = relation; - joinColumn.target = joinColumnMetadataArgs.target; - joinColumn.propertyName = joinColumnMetadataArgs.propertyName; - const referencedColumn = columnMetadatas.find(column => { - return column.propertyName === joinColumnMetadataArgs.referencedColumnName; - }); - if (!referencedColumn) - throw new Error(`Referenced column ${joinColumnMetadataArgs.referencedColumnName} was not found in entity ${relation.inverseEntityMetadata.name}`); // todo: fix ${relation.inverseEntityMetadata.name} - - joinColumn.referencedColumn = referencedColumn; - joinColumn.name = joinColumnMetadataArgs.name || columnNameFactory(joinColumn.referencedColumn.propertyName); - return joinColumn; - }); - }*/ - } \ No newline at end of file diff --git a/src/metadata-builder/EntityMetadataValidator.ts b/src/metadata-builder/EntityMetadataValidator.ts index 31bd43c2e..e3588035d 100644 --- a/src/metadata-builder/EntityMetadataValidator.ts +++ b/src/metadata-builder/EntityMetadataValidator.ts @@ -29,7 +29,7 @@ export class EntityMetadataValidator { validate(entityMetadata: EntityMetadata, allEntityMetadatas: EntityMetadata[]) { // check if table metadata has an id - if (!entityMetadata.table.isClassTableChild && !entityMetadata.primaryColumns.length && !entityMetadata.junction) + if (!entityMetadata.isClassTableChild && !entityMetadata.primaryColumns.length && !entityMetadata.junction) throw new MissingPrimaryColumnError(entityMetadata); // validate if table is using inheritance it has a discriminator diff --git a/src/metadata/EmbeddedMetadata.ts b/src/metadata/EmbeddedMetadata.ts index 9516cbdd9..e3c8bb1bd 100644 --- a/src/metadata/EmbeddedMetadata.ts +++ b/src/metadata/EmbeddedMetadata.ts @@ -1,5 +1,4 @@ import {EntityMetadata} from "./EntityMetadata"; -import {TableMetadata} from "./TableMetadata"; import {ColumnMetadata} from "./ColumnMetadata"; import {EmbeddedMetadataArgs} from "../metadata-args/EmbeddedMetadataArgs"; @@ -31,11 +30,6 @@ export class EmbeddedMetadata { */ readonly propertyName: string; - /** - * Embeddable table. - */ - readonly table: TableMetadata; - /** * Embeddable table's columns. */ @@ -66,15 +60,13 @@ export class EmbeddedMetadata { // Constructor // --------------------------------------------------------------------- - constructor(table: TableMetadata, - columns: ColumnMetadata[], + constructor(columns: ColumnMetadata[], embeddeds: EmbeddedMetadata[], args: EmbeddedMetadataArgs) { this.type = args.type ? args.type() : undefined; this.propertyName = args.propertyName; this.isArray = args.isArray; this.customPrefix = args.prefix; - this.table = table; this.columns = columns; this.embeddeds = embeddeds; this.embeddeds.forEach(embedded => { diff --git a/src/metadata/EntityMetadata.ts b/src/metadata/EntityMetadata.ts index ef1b247f0..3e59059a6 100644 --- a/src/metadata/EntityMetadata.ts +++ b/src/metadata/EntityMetadata.ts @@ -1,6 +1,5 @@ -import {TableMetadata} from "./TableMetadata"; import {ColumnMetadata} from "./ColumnMetadata"; -import {RelationMetadata, PropertyTypeInFunction} from "./RelationMetadata"; +import {PropertyTypeInFunction, RelationMetadata} from "./RelationMetadata"; import {IndexMetadata} from "./IndexMetadata"; import {RelationTypes} from "./types/RelationTypes"; import {ForeignKeyMetadata} from "./ForeignKeyMetadata"; @@ -11,6 +10,8 @@ import {ObjectLiteral} from "../common/ObjectLiteral"; import {LazyRelationsWrapper} from "../lazy-loading/LazyRelationsWrapper"; import {RelationIdMetadata} from "./RelationIdMetadata"; import {RelationCountMetadata} from "./RelationCountMetadata"; +import {TableType, TableTypes} from "./types/TableTypes"; +import {OrderByCondition} from "../find-options/OrderByCondition"; // todo: IDEA. store all entity metadata in the EntityMetadata too? (this will open more features for metadata objects + no need to access connection in lot of places) @@ -56,7 +57,12 @@ export class EntityMetadata { /** * Entity's table metadata. */ - readonly table: TableMetadata; + readonly _tableName?: string; + + /** + * Specifies a default order by used for queries from this table when no explicit order by is specified. + */ + readonly _orderBy?: OrderByCondition|((object: any) => OrderByCondition|any); /** * Entity's relation metadatas. @@ -105,6 +111,21 @@ export class EntityMetadata { */ readonly tablesPrefix?: string; + /** + * Table's database engine type (like "InnoDB", "MyISAM", etc). + */ + readonly engine?: string; + + /** + * Whether table must be synced during schema build or not + */ + readonly skipSchemaSync?: boolean; + + /** + * Table type. Tables can be abstract, closure, junction, embedded, etc. + */ + tableType: TableType = "regular"; + // ------------------------------------------------------------------------- // Private properties // ------------------------------------------------------------------------- @@ -124,7 +145,8 @@ export class EntityMetadata { this.junction = args.junction; this.tablesPrefix = args.tablesPrefix; this.namingStrategy = args.namingStrategy; - this.table = args.tableMetadata; + this._tableName = args.tableName; + this.tableType = args.tableType; this._columns = args.columnMetadatas || []; this.relations = args.relationMetadatas || []; this.relationIds = args.relationIdMetadatas || []; @@ -134,8 +156,9 @@ export class EntityMetadata { this.embeddeds = args.embeddedMetadatas || []; this.discriminatorValue = args.discriminatorValue; this.inheritanceType = args.inheritanceType; - - this.table.entityMetadata = this; + this.engine = args.engine; + this.skipSchemaSync = args.skipSchemaSync; + this._orderBy = args.orderBy; this._columns.forEach(column => column.entityMetadata = this); this.relations.forEach(relation => relation.entityMetadata = this); this.relationIds.forEach(relationId => relationId.entityMetadata = this); @@ -161,10 +184,43 @@ export class EntityMetadata { * Entity's name. Equal to entity target class's name if target is set to table, or equals to table name if its set. */ get name(): string { - if (!this.table) - throw new Error("No table target set to the entity metadata."); + return this.targetName ? this.targetName : this.tableName; + } - return this.targetName ? this.targetName : this.table.name; + /** + * Entity's name. Equal to entity target class's name if target is set to table, or equals to table name if its set. + */ + get tableName(): string { + if (this.tablesPrefix) + return this.namingStrategy.prefixTableName(this.tablesPrefix, this.tableNameWithoutPrefix); + + return this.tableNameWithoutPrefix; + } + + /** + * Gets the table name without global table prefix. + * When querying table you need a table name with prefix, but in some scenarios, + * for example when you want to name a junction table that contains names of two other tables, + * you may want a table name without prefix. + */ + get tableNameWithoutPrefix() { + if (this.isClosureJunction && this._tableName) + return this.namingStrategy.closureJunctionTableName(this._tableName); + + // otherwise generate table name from target's name + const name = this.target instanceof Function ? (this.target as any).name : this.target; + return this.namingStrategy.tableName(name, this._tableName); + } + + /** + * Specifies a default order by used for queries from this table when no explicit order by is specified. + * If default order by was not set, then returns undefined. + */ + get orderBy(): OrderByCondition|undefined { + if (this._orderBy instanceof Function) + return this._orderBy(this.createPropertiesMap()); + + return this._orderBy; } /** @@ -963,4 +1019,70 @@ export class EntityMetadata { // return this.relationsWithJoinColumns.some(relation => relation.isNullable || relation.isPrimary); } + /** + * Checks if this table is regular. + * All non-specific tables are just regular tables. Its a default table type. + */ + get isRegular() { + return this.tableType === TableTypes.REGULAR; + } + + /** + * Checks if this table is abstract. + * This type is for the tables that does not exist in the database, + * but provide columns and relations for the tables of the child classes who inherit them. + */ + get isAbstract() { + return this.tableType === TableTypes.ABSTRACT; + } + + /** + * Checks if this table is abstract. + * Junction table is a table automatically created by many-to-many relationship. + */ + get isJunction() { + return this.tableType === TableTypes.JUNCTION; + } + + /** + * Checks if this table is a closure table. + * Closure table is one of the tree-specific tables that supports closure database pattern. + */ + get isClosure() { + return this.tableType === TableTypes.CLOSURE; + } + + /** + * Checks if this table is a junction table of the closure table. + * This type is for tables that contain junction metadata of the closure tables. + */ + get isClosureJunction() { + return this.tableType === TableTypes.CLOSURE_JUNCTION; + } + + /** + * Checks if this table is an embeddable table. + * Embeddable tables are not stored in the database as separate tables. + * Instead their columns are embed into tables who owns them. + */ + get isEmbeddable() { + return this.tableType === TableTypes.EMBEDDABLE; + } + + /** + * 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. + */ + get isSingleTableChild() { + return this.tableType === TableTypes.SINGLE_TABLE_CHILD; + } + + /** + * 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. + */ + get isClassTableChild() { + return this.tableType === TableTypes.CLASS_TABLE_CHILD; + } + } \ No newline at end of file diff --git a/src/metadata/ForeignKeyMetadata.ts b/src/metadata/ForeignKeyMetadata.ts index 06b80f910..f7033a103 100644 --- a/src/metadata/ForeignKeyMetadata.ts +++ b/src/metadata/ForeignKeyMetadata.ts @@ -1,5 +1,4 @@ import {ColumnMetadata} from "./ColumnMetadata"; -import {TableMetadata} from "./TableMetadata"; import {EntityMetadata} from "./EntityMetadata"; /** @@ -21,6 +20,11 @@ export class ForeignKeyMetadata { */ entityMetadata: EntityMetadata; + /** + * Entity metadata which this foreign key is references. + */ + referencedEntityMetadata: EntityMetadata; + // ------------------------------------------------------------------------- // Public Readonly Properties // ------------------------------------------------------------------------- @@ -30,11 +34,6 @@ export class ForeignKeyMetadata { */ readonly columns: ColumnMetadata[]; - /** - * Table to which this foreign key is references. - */ - readonly referencedTable: TableMetadata; - /** * Array of referenced columns. */ @@ -50,11 +49,11 @@ export class ForeignKeyMetadata { // ------------------------------------------------------------------------- constructor(columns: ColumnMetadata[], - referencedTable: TableMetadata, + referencedEntityMetadata: EntityMetadata, referencedColumns: ColumnMetadata[], onDelete?: OnDeleteType) { this.columns = columns; - this.referencedTable = referencedTable; + this.referencedEntityMetadata = referencedEntityMetadata; this.referencedColumns = referencedColumns; if (onDelete) this.onDelete = onDelete; @@ -68,21 +67,21 @@ export class ForeignKeyMetadata { * Gets the table name to which this foreign key is applied. */ get tableName() { - return this.entityMetadata.table.name; + return this.entityMetadata.tableName; } /** * Gets the table name to which this foreign key is referenced. */ get referencedTableName() { - return this.referencedTable.name; + return this.referencedEntityMetadata.tableName; } /** * Gets foreign key name. */ get name() { - return this.entityMetadata.namingStrategy.foreignKeyName(this.tableName, this.columnNames, this.referencedTable.name, this.referencedColumnNames); + return this.entityMetadata.namingStrategy.foreignKeyName(this.tableName, this.columnNames, this.referencedEntityMetadata.tableName, this.referencedColumnNames); } /** diff --git a/src/metadata/IndexMetadata.ts b/src/metadata/IndexMetadata.ts index 951a48ada..6504874ce 100644 --- a/src/metadata/IndexMetadata.ts +++ b/src/metadata/IndexMetadata.ts @@ -62,14 +62,14 @@ export class IndexMetadata { * Gets index's name. */ get name() { - return this.entityMetadata.namingStrategy.indexName(this._name, this.entityMetadata.table.name, this.columns); + return this.entityMetadata.namingStrategy.indexName(this._name, this.entityMetadata.tableName, this.columns); } /** * Gets the table name on which index is applied. */ get tableName() { - return this.entityMetadata.table.name; + return this.entityMetadata.tableName; } /** diff --git a/src/metadata/RelationMetadata.ts b/src/metadata/RelationMetadata.ts index dedefb10a..813a88c09 100644 --- a/src/metadata/RelationMetadata.ts +++ b/src/metadata/RelationMetadata.ts @@ -1,6 +1,6 @@ -import {RelationTypes, RelationType} from "./types/RelationTypes"; +import {RelationType, RelationTypes} from "./types/RelationTypes"; import {EntityMetadata} from "./EntityMetadata"; -import {OnDeleteType, ForeignKeyMetadata} from "./ForeignKeyMetadata"; +import {ForeignKeyMetadata, OnDeleteType} from "./ForeignKeyMetadata"; import {RelationMetadataArgs} from "../metadata-args/RelationMetadataArgs"; import {ObjectLiteral} from "../common/ObjectLiteral"; import {ColumnMetadata} from "./ColumnMetadata"; @@ -209,7 +209,7 @@ export class RelationMetadata { * Join table name. */ get joinTableName(): string { - return this.junctionEntityMetadata.table.name; + return this.junctionEntityMetadata.tableName; } diff --git a/src/metadata/TableMetadata.ts b/src/metadata/TableMetadata.ts deleted file mode 100644 index a28c4c1db..000000000 --- a/src/metadata/TableMetadata.ts +++ /dev/null @@ -1,205 +0,0 @@ -import {EntityMetadata} from "./EntityMetadata"; -import {TableMetadataArgs} from "../metadata-args/TableMetadataArgs"; -import {OrderByCondition} from "../find-options/OrderByCondition"; -import {TableType, TableTypes} from "./types/TableTypes"; -import {EntityMetadataAlreadySetError} from "./error/EntityMetadataAlreadySetError"; -import {EntityMetadataNotSetError} from "./error/EntityMetadataNotSetError"; - -/** - * TableMetadata contains all entity's table metadata and information. - */ -export class TableMetadata { - - // --------------------------------------------------------------------- - // Public Properties - // --------------------------------------------------------------------- - - /** - * Target class to which metadata is applied. - * Function target is a table defined in the class. - * String target is a table defined in a json schema. - * "__virtual__" is a table defined without target class (like junction tables). - */ - readonly target: Function|string|"__virtual__"; - - /** - * Specifies a default order by used for queries from this table when no explicit order by is specified. - */ - readonly _orderBy?: OrderByCondition|((object: any) => OrderByCondition|any); - - /** - * Table's database engine type (like "InnoDB", "MyISAM", etc). - */ - readonly engine?: string; - - /** - * Whether table must be synced during schema build or not - */ - readonly skipSchemaSync?: boolean; - - // --------------------------------------------------------------------- - // Private Properties - // --------------------------------------------------------------------- - - /** - * Table type. Tables can be abstract, closure, junction, embedded, etc. - */ - private readonly tableType: TableType = "regular"; - - /** - * Table name in the database. If name is not set then table's name will be generated from target's name. - */ - private readonly _name?: string; - - /** - * EntityMetadata of this table metadata, where this table metadata contained. - */ - private _entityMetadata?: EntityMetadata; - - // --------------------------------------------------------------------- - // Constructor - // --------------------------------------------------------------------- - - /** - * Creates a new TableMetadata based on the given arguments object. - */ - constructor(args: TableMetadataArgs) { - this.target = args.target; - this.tableType = args.type; - this._name = args.name; - this._orderBy = args.orderBy; - this.engine = args.engine; - this.skipSchemaSync = args.skipSchemaSync; - } - - // --------------------------------------------------------------------- - // Accessors - // --------------------------------------------------------------------- - - /** - * Sets the entity metadata of this table metadata. - * Note that entity metadata can be set only once. - * Once you set it, you can't change it anymore. - */ - set entityMetadata(metadata: EntityMetadata) { - if (this._entityMetadata) - throw new EntityMetadataAlreadySetError(TableMetadata, this.target, this._name); - - this._entityMetadata = metadata; - } - - /** - * Gets entity metadata of this table metadata. - * If entity metadata was not set then exception will be thrown. - */ - get entityMetadata(): EntityMetadata { - if (!this._entityMetadata) - throw new EntityMetadataNotSetError(TableMetadata, this.target, this._name); - - return this._entityMetadata; - } - - /** - * Gets the table name without global table prefix. - * When querying table you need a table name with prefix, but in some scenarios, - * for example when you want to name a junction table that contains names of two other tables, - * you may want a table name without prefix. - */ - get nameWithoutPrefix() { - if (this.isClosureJunction && this._name) - return this.entityMetadata.namingStrategy.closureJunctionTableName(this._name); - - // otherwise generate table name from target's name - const name = this.target instanceof Function ? (this.target as any).name : this.target; - return this.entityMetadata.namingStrategy.tableName(name, this._name); - } - - /** - * Table name in the database. - * This name includes global table prefix if it was set. - */ - get name(): string { - if (this.entityMetadata.tablesPrefix) - return this.entityMetadata.namingStrategy.prefixTableName(this.entityMetadata.tablesPrefix, this.nameWithoutPrefix); - - return this.nameWithoutPrefix; - } - - /** - * Specifies a default order by used for queries from this table when no explicit order by is specified. - * If default order by was not set, then returns undefined. - */ - get orderBy(): OrderByCondition|undefined { - if (this._orderBy instanceof Function) - return this._orderBy(this.entityMetadata.createPropertiesMap()); - - return this._orderBy; - } - - /** - * Checks if this table is regular. - * All non-specific tables are just regular tables. Its a default table type. - */ - get isRegular() { - return this.tableType === TableTypes.REGULAR; - } - - /** - * Checks if this table is abstract. - * This type is for the tables that does not exist in the database, - * but provide columns and relations for the tables of the child classes who inherit them. - */ - get isAbstract() { - return this.tableType === TableTypes.ABSTRACT; - } - - /** - * Checks if this table is abstract. - * Junction table is a table automatically created by many-to-many relationship. - */ - get isJunction() { - return this.tableType === TableTypes.JUNCTION; - } - - /** - * Checks if this table is a closure table. - * Closure table is one of the tree-specific tables that supports closure database pattern. - */ - get isClosure() { - return this.tableType === TableTypes.CLOSURE; - } - - /** - * Checks if this table is a junction table of the closure table. - * This type is for tables that contain junction metadata of the closure tables. - */ - get isClosureJunction() { - return this.tableType === TableTypes.CLOSURE_JUNCTION; - } - - /** - * Checks if this table is an embeddable table. - * Embeddable tables are not stored in the database as separate tables. - * Instead their columns are embed into tables who owns them. - */ - get isEmbeddable() { - return this.tableType === TableTypes.EMBEDDABLE; - } - - /** - * 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. - */ - get isSingleTableChild() { - return this.tableType === TableTypes.SINGLE_TABLE_CHILD; - } - - /** - * 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. - */ - get isClassTableChild() { - return this.tableType === TableTypes.CLASS_TABLE_CHILD; - } - -} diff --git a/src/metadata/error/EntityMetadataAlreadySetError.ts b/src/metadata/error/EntityMetadataAlreadySetError.ts deleted file mode 100644 index e5ce4a00b..000000000 --- a/src/metadata/error/EntityMetadataAlreadySetError.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Thrown when user tries to execute operation that requires connection to be established. - */ -export class EntityMetadataAlreadySetError extends Error { - name = "EntityMetadataAlreadySetError"; - - constructor(type: Function, target: Function|string|undefined, tableName: string|undefined) { - super(); - const targetMessage = target ? ` for ${ target instanceof Function ? (target.constructor as any).name : target }` : ""; - const tableNameMessage = tableName ? ` with ${ tableName } table name` : ""; - this.message = "Entity metadata" + targetMessage + tableNameMessage + " has been already set to this " + (type.constructor as any).name; - } - -} \ No newline at end of file diff --git a/src/metadata/error/EntityMetadataNotSetError.ts b/src/metadata/error/EntityMetadataNotSetError.ts deleted file mode 100644 index ce629bb60..000000000 --- a/src/metadata/error/EntityMetadataNotSetError.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Thrown when accessed to the class with entity metadata, - * however on that time entity metadata is not set in the class. - */ -export class EntityMetadataNotSetError extends Error { - name = "EntityMetadataNotSetError"; - - constructor(type: Function, target: Function|string|undefined, tableName: string|undefined) { - super(); - const targetMessage = target ? ` for ${ target instanceof Function ? (target.constructor as any).name : target }` : ""; - const tableNameMessage = tableName ? ` with ${ tableName } table name` : ""; - this.message = "Entity metadata" + targetMessage + tableNameMessage + " is not set in " + (type.constructor as any).name; - } - -} \ No newline at end of file diff --git a/src/persistence/SubjectBuilder.ts b/src/persistence/SubjectBuilder.ts index 60eff9ce6..545b0ce78 100644 --- a/src/persistence/SubjectBuilder.ts +++ b/src/persistence/SubjectBuilder.ts @@ -300,7 +300,7 @@ export class SubjectBuilder { // note: we can't use extractRelationValuesFromEntity here because it does not handle empty arrays const promises = subject.metadata.relations.map(async relation => { const valueMetadata = relation.inverseEntityMetadata; - const qbAlias = valueMetadata.table.name; + const qbAlias = valueMetadata.tableName; // added for type-safety, but subject without databaseEntity cant come here anyway because of checks on upper levels if (!subject.hasDatabaseEntity) return; @@ -555,7 +555,7 @@ export class SubjectBuilder { databaseEntities = await this.connection .getRepository(valueMetadata.target) .createQueryBuilder(qbAlias, this.queryRunnerProvider) // todo: this wont work for mongodb. implement this in some method and call it here instead? - .innerJoin(relation.junctionEntityMetadata.table.name, joinAlias, conditions) + .innerJoin(relation.junctionEntityMetadata.tableName, joinAlias, conditions) .setParameters(parameters) .enableAutoRelationIdsLoad() .getMany(); @@ -586,7 +586,7 @@ export class SubjectBuilder { databaseEntities = await this.connection .getRepository(valueMetadata.target) .createQueryBuilder(qbAlias, this.queryRunnerProvider) // todo: this wont work for mongodb. implement this in some method and call it here instead? - .innerJoin(relation.junctionEntityMetadata.table.name, joinAlias, conditions) + .innerJoin(relation.junctionEntityMetadata.tableName, joinAlias, conditions) .setParameters(parameters) .enableAutoRelationIdsLoad() .getMany(); diff --git a/src/persistence/SubjectOperationExecutor.ts b/src/persistence/SubjectOperationExecutor.ts index 3664ccc7a..d2ed7c345 100644 --- a/src/persistence/SubjectOperationExecutor.ts +++ b/src/persistence/SubjectOperationExecutor.ts @@ -2,7 +2,7 @@ import {ObjectLiteral} from "../common/ObjectLiteral"; import {EntityMetadata} from "../metadata/EntityMetadata"; import {Connection} from "../connection/Connection"; import {QueryRunner} from "../query-runner/QueryRunner"; -import {Subject, JunctionInsert, JunctionRemove} from "./Subject"; +import {JunctionInsert, JunctionRemove, Subject} from "./Subject"; import {OrmUtils} from "../util/OrmUtils"; import {QueryRunnerProvider} from "../query-runner/QueryRunnerProvider"; import {EntityManager} from "../entity-manager/EntityManager"; @@ -318,7 +318,7 @@ export class SubjectOperationExecutor { if (!Object.keys(conditions).length) return; - const updatePromise = this.queryRunner.update(subject.metadata.table.name, updateOptions, conditions); + const updatePromise = this.queryRunner.update(subject.metadata.tableName, updateOptions, conditions); updatePromises.push(updatePromise); } @@ -397,7 +397,7 @@ export class SubjectOperationExecutor { updateOptions[joinColumn.fullName] = subject.entity[referencedColumn.propertyName] || subject.newlyGeneratedId || subRelatedEntity.generatedObjectId; } - const updatePromise = this.queryRunner.update(relation.inverseEntityMetadata.table.name, updateOptions, conditions); + const updatePromise = this.queryRunner.update(relation.inverseEntityMetadata.tableName, updateOptions, conditions); updatePromises.push(updatePromise); }); @@ -423,21 +423,21 @@ export class SubjectOperationExecutor { let newlyGeneratedId: any, parentGeneratedId: any; // if entity uses class table inheritance then we need to separate entity into sub values that will be inserted into multiple tables - if (metadata.table.isClassTableChild) { // todo: with current implementation inheritance of multiple class table children will not work + if (metadata.isClassTableChild) { // todo: with current implementation inheritance of multiple class table children will not work // first insert entity values into parent class table const parentValuesMap = this.collectColumnsAndValues(parentEntityMetadata, entity, subject.date, undefined, metadata.discriminatorValue, alreadyInsertedSubjects); - newlyGeneratedId = parentGeneratedId = await this.queryRunner.insert(parentEntityMetadata.table.name, parentValuesMap, parentEntityMetadata.generatedColumnIfExist); + newlyGeneratedId = parentGeneratedId = await this.queryRunner.insert(parentEntityMetadata.tableName, parentValuesMap, parentEntityMetadata.generatedColumnIfExist); // second insert entity values into child class table const childValuesMap = this.collectColumnsAndValues(metadata, entity, subject.date, newlyGeneratedId, undefined, alreadyInsertedSubjects); - const secondGeneratedId = await this.queryRunner.insert(metadata.table.name, childValuesMap, metadata.generatedColumnIfExist); + const secondGeneratedId = await this.queryRunner.insert(metadata.tableName, childValuesMap, metadata.generatedColumnIfExist); if (!newlyGeneratedId && secondGeneratedId) newlyGeneratedId = secondGeneratedId; } else { // in the case when class table inheritance is not used const valuesMap = this.collectColumnsAndValues(metadata, entity, subject.date, undefined, undefined, alreadyInsertedSubjects); - newlyGeneratedId = await this.queryRunner.insert(metadata.table.name, valuesMap, metadata.generatedColumnIfExist); + newlyGeneratedId = await this.queryRunner.insert(metadata.tableName, valuesMap, metadata.generatedColumnIfExist); } if (parentGeneratedId) @@ -637,7 +637,7 @@ export class SubjectOperationExecutor { */ private executeInsertClosureTableOperations(/*, updatesByRelations: Subject[]*/) { // todo: what to do with updatesByRelations const promises = this.insertSubjects - .filter(subject => subject.metadata.table.isClosure) + .filter(subject => subject.metadata.isClosure) .map(async subject => { // const relationsUpdateMap = this.findUpdateOperationForEntity(updatesByRelations, insertSubjects, subject.entity); // subject.treeLevel = await this.insertIntoClosureTable(subject, relationsUpdateMap); @@ -652,7 +652,7 @@ export class SubjectOperationExecutor { private async insertClosureTableValues(subject: Subject): Promise { // todo: since closure tables do not support compose primary keys - throw an exception? // todo: what if parent entity or parentEntityId is empty?! - const tableName = subject.metadata.closureJunctionTable.table.name; + const tableName = subject.metadata.closureJunctionTable.tableName; const referencedColumn = subject.metadata.treeParentRelation.joinColumns[0].referencedColumn; // todo: check if joinColumn works // todo: fix joinColumns[0] usage @@ -676,7 +676,7 @@ export class SubjectOperationExecutor { // try to find parent entity id in some other entity that has this entity in its children if (!parentEntityId) { const parentSubject = this.allSubjects.find(allSubject => { - if (!allSubject.hasEntity || !allSubject.metadata.table.isClosure || !allSubject.metadata.hasTreeChildrenRelation) + if (!allSubject.hasEntity || !allSubject.metadata.isClosure || !allSubject.metadata.hasTreeChildrenRelation) return false; const children = allSubject.entity[subject.metadata.treeChildrenRelation.propertyName]; @@ -696,7 +696,7 @@ export class SubjectOperationExecutor { if (subject.metadata.hasTreeLevelColumn) { const values = { [subject.metadata.treeLevelColumn.fullName]: subject.treeLevel }; - await this.queryRunner.update(subject.metadata.table.name, values, { [referencedColumn.fullName]: newEntityId }); + await this.queryRunner.update(subject.metadata.tableName, values, { [referencedColumn.fullName]: newEntityId }); } } @@ -765,7 +765,7 @@ export class SubjectOperationExecutor { if (subject.metadata.hasVersionColumn) value[subject.metadata.versionColumn.fullName] = this.connection.driver.preparePersistentValue(entity[subject.metadata.versionColumn.propertyName] + 1, subject.metadata.versionColumn); - return this.queryRunner.update(subject.metadata.table.name, value, idMap); + return this.queryRunner.update(subject.metadata.tableName, value, idMap); } // we group by table name, because metadata can have different table names @@ -774,9 +774,9 @@ export class SubjectOperationExecutor { subject.diffColumns.forEach(column => { if (!column.entityTarget) return; // todo: how this can be possible? const metadata = this.connection.getMetadata(column.entityTarget); - let valueMap = valueMaps.find(valueMap => valueMap.tableName === metadata.table.name); + let valueMap = valueMaps.find(valueMap => valueMap.tableName === metadata.tableName); if (!valueMap) { - valueMap = { tableName: metadata.table.name, metadata: metadata, values: {} }; + valueMap = { tableName: metadata.tableName, metadata: metadata, values: {} }; valueMaps.push(valueMap); } @@ -785,9 +785,9 @@ export class SubjectOperationExecutor { subject.diffRelations.forEach(relation => { const metadata = this.connection.getMetadata(relation.entityTarget); - let valueMap = valueMaps.find(valueMap => valueMap.tableName === metadata.table.name); + let valueMap = valueMaps.find(valueMap => valueMap.tableName === metadata.tableName); if (!valueMap) { - valueMap = { tableName: metadata.table.name, metadata: metadata, values: {} }; + valueMap = { tableName: metadata.tableName, metadata: metadata, values: {} }; valueMaps.push(valueMap); } @@ -802,9 +802,9 @@ export class SubjectOperationExecutor { return; if (subject.metadata.hasUpdateDateColumn) { - let valueMap = valueMaps.find(valueMap => valueMap.tableName === subject.metadata.table.name); + let valueMap = valueMaps.find(valueMap => valueMap.tableName === subject.metadata.tableName); if (!valueMap) { - valueMap = { tableName: subject.metadata.table.name, metadata: subject.metadata, values: {} }; + valueMap = { tableName: subject.metadata.tableName, metadata: subject.metadata, values: {} }; valueMaps.push(valueMap); } @@ -812,9 +812,9 @@ export class SubjectOperationExecutor { } if (subject.metadata.hasVersionColumn) { - let valueMap = valueMaps.find(valueMap => valueMap.tableName === subject.metadata.table.name); + let valueMap = valueMaps.find(valueMap => valueMap.tableName === subject.metadata.tableName); if (!valueMap) { - valueMap = { tableName: subject.metadata.table.name, metadata: subject.metadata, values: {} }; + valueMap = { tableName: subject.metadata.tableName, metadata: subject.metadata, values: {} }; valueMaps.push(valueMap); } @@ -823,10 +823,10 @@ export class SubjectOperationExecutor { if (subject.metadata.parentEntityMetadata) { if (subject.metadata.parentEntityMetadata.hasUpdateDateColumn) { - let valueMap = valueMaps.find(valueMap => valueMap.tableName === subject.metadata.parentEntityMetadata.table.name); + let valueMap = valueMaps.find(valueMap => valueMap.tableName === subject.metadata.parentEntityMetadata.tableName); if (!valueMap) { valueMap = { - tableName: subject.metadata.parentEntityMetadata.table.name, + tableName: subject.metadata.parentEntityMetadata.tableName, metadata: subject.metadata.parentEntityMetadata, values: {} }; @@ -837,10 +837,10 @@ export class SubjectOperationExecutor { } if (subject.metadata.parentEntityMetadata.hasVersionColumn) { - let valueMap = valueMaps.find(valueMap => valueMap.tableName === subject.metadata.parentEntityMetadata.table.name); + let valueMap = valueMaps.find(valueMap => valueMap.tableName === subject.metadata.parentEntityMetadata.tableName); if (!valueMap) { valueMap = { - tableName: subject.metadata.parentEntityMetadata.table.name, + tableName: subject.metadata.parentEntityMetadata.tableName, metadata: subject.metadata.parentEntityMetadata, values: {} }; @@ -887,7 +887,7 @@ export class SubjectOperationExecutor { if (!idMap) throw new Error(`Internal error. Cannot get id of the updating entity.`); - return this.queryRunner.update(subject.metadata.table.name, values, idMap); + return this.queryRunner.update(subject.metadata.tableName, values, idMap); } // ------------------------------------------------------------------------- @@ -910,15 +910,15 @@ export class SubjectOperationExecutor { subject.metadata.parentPrimaryColumns.forEach(column => { parentConditions[column.fullName] = subject.databaseEntity[column.propertyName]; }); - await this.queryRunner.delete(subject.metadata.parentEntityMetadata.table.name, parentConditions); + await this.queryRunner.delete(subject.metadata.parentEntityMetadata.tableName, parentConditions); const childConditions: ObjectLiteral = {}; subject.metadata.primaryColumnsWithParentIdColumns.forEach(column => { childConditions[column.fullName] = subject.databaseEntity[column.propertyName]; }); - await this.queryRunner.delete(subject.metadata.table.name, childConditions); + await this.queryRunner.delete(subject.metadata.tableName, childConditions); } else { - await this.queryRunner.delete(subject.metadata.table.name, subject.metadata.getEntityIdColumnMap(subject.databaseEntity)!); + await this.queryRunner.delete(subject.metadata.tableName, subject.metadata.getEntityIdColumnMap(subject.databaseEntity)!); } } @@ -985,7 +985,7 @@ export class SubjectOperationExecutor { const columns = relation.junctionEntityMetadata.columnsWithoutEmbeddeds.map(column => column.fullName); const values = relation.isOwning ? [...ownId, ...relationId] : [...relationId, ...ownId]; - return this.queryRunner.insert(relation.junctionEntityMetadata.table.name, OrmUtils.zipObject(columns, values)); + return this.queryRunner.insert(relation.junctionEntityMetadata.tableName, OrmUtils.zipObject(columns, values)); }); await Promise.all(promises); @@ -1029,7 +1029,7 @@ export class SubjectOperationExecutor { const joinColumn = secondJoinColumns.find(column => column.referencedColumn.propertyName === key); inverseConditions[joinColumn!.fullName] = entity[joinColumn!.referencedColumn.propertyName]; }); - return this.queryRunner.delete(junctionMetadata.table.name, Object.assign({}, inverseConditions, conditions)); + return this.queryRunner.delete(junctionMetadata.tableName, Object.assign({}, inverseConditions, conditions)); }); await Promise.all(removePromises); diff --git a/src/query-builder/JoinAttribute.ts b/src/query-builder/JoinAttribute.ts index ae58ba41e..8485f2eee 100644 --- a/src/query-builder/JoinAttribute.ts +++ b/src/query-builder/JoinAttribute.ts @@ -78,7 +78,7 @@ export class JoinAttribute { * Name of the table which we should join. */ get tableName(): string { - return this.metadata ? this.metadata.table.name : this.entityOrProperty as string; + return this.metadata ? this.metadata.tableName : this.entityOrProperty as string; } /** @@ -146,7 +146,7 @@ export class JoinAttribute { return metadata; // check if we have entity with such table name, and use its metadata if found - return this.connection.entityMetadatas.find(metadata => metadata.table.name === this.entityOrProperty); + return this.connection.entityMetadatas.find(metadata => metadata.tableName === this.entityOrProperty); } return undefined; diff --git a/src/query-builder/QueryBuilder.ts b/src/query-builder/QueryBuilder.ts index 8b0653345..480df5bb3 100644 --- a/src/query-builder/QueryBuilder.ts +++ b/src/query-builder/QueryBuilder.ts @@ -214,7 +214,7 @@ export class QueryBuilder { fromTable(tableName: string, aliasName: string) { // if table has a metadata then find it to properly escape its properties - const metadata = this.connection.entityMetadatas.find(metadata => metadata.table.name === tableName); + const metadata = this.connection.entityMetadatas.find(metadata => metadata.tableName === tableName); if (metadata) { this.expressionMap.createMainAlias({ name: aliasName, @@ -1256,7 +1256,7 @@ export class QueryBuilder { const aliasName = this.expressionMap.mainAlias.name; if (this.expressionMap.mainAlias.hasMetadata) { - tableName = this.expressionMap.mainAlias.metadata.table.name; + tableName = this.expressionMap.mainAlias.metadata.tableName; allSelects.push(...this.buildEscapedEntityColumnSelects(aliasName, this.expressionMap.mainAlias.metadata)); excludedSelects.push(...this.findEntityColumnSelects(aliasName, this.expressionMap.mainAlias.metadata)); @@ -1282,7 +1282,7 @@ export class QueryBuilder { if (!this.expressionMap.ignoreParentTablesJoins && this.expressionMap.mainAlias.hasMetadata) { if (this.expressionMap.mainAlias!.metadata.parentEntityMetadata && this.expressionMap.mainAlias!.metadata.parentIdColumns) { - const alias = "parentIdColumn_" + ea(this.expressionMap.mainAlias!.metadata.parentEntityMetadata.table.name); + const alias = "parentIdColumn_" + ea(this.expressionMap.mainAlias!.metadata.parentEntityMetadata.tableName); this.expressionMap.mainAlias!.metadata.parentEntityMetadata.columns.forEach(column => { // TODO implement partial select allSelects.push({ selection: ea(alias + "." + column.fullName), aliasName: alias + "_" + column.fullName }); @@ -1470,7 +1470,7 @@ export class QueryBuilder { return " " + joinAttr.direction + " JOIN " + et(destinationTableName) + " " + ea(destinationTableAlias) + " ON " + condition + appendedCondition; } else { // means many-to-many - const junctionTableName = relation.junctionEntityMetadata.table.name; + const junctionTableName = relation.junctionEntityMetadata.tableName; const junctionAlias = joinAttr.junctionAlias; let junctionCondition = "", destinationCondition = ""; @@ -1509,8 +1509,8 @@ export class QueryBuilder { if (!this.expressionMap.ignoreParentTablesJoins && this.expressionMap.mainAlias!.hasMetadata) { const metadata = this.expressionMap.mainAlias!.metadata; if (metadata.parentEntityMetadata && metadata.parentIdColumns) { - const alias = "parentIdColumn_" + metadata.parentEntityMetadata.table.name; - const parentJoin = " JOIN " + et(metadata.parentEntityMetadata.table.name) + " " + ea(alias) + " ON " + + const alias = "parentIdColumn_" + metadata.parentEntityMetadata.tableName; + const parentJoin = " JOIN " + et(metadata.parentEntityMetadata.tableName) + " " + ea(alias) + " ON " + metadata.parentIdColumns.map(parentIdColumn => { return this.expressionMap.mainAlias!.name + "." + parentIdColumn.fullName + "=" + ea(alias) + "." + parentIdColumn.propertyName; }); @@ -1531,7 +1531,7 @@ export class QueryBuilder { // if table has a default order then apply it let orderBys = this.expressionMap.orderBys; if (!Object.keys(orderBys).length && this.expressionMap.mainAlias!.hasMetadata) { - orderBys = this.expressionMap.mainAlias!.metadata.table.orderBy || {}; + orderBys = this.expressionMap.mainAlias!.metadata.orderBy || {}; } const selectString = Object.keys(orderBys) @@ -1557,7 +1557,7 @@ export class QueryBuilder { // if table has a default order then apply it if (!Object.keys(orderBys).length && this.expressionMap.mainAlias!.hasMetadata) { - orderBys = this.expressionMap.mainAlias!.metadata.table.orderBy || {}; + orderBys = this.expressionMap.mainAlias!.metadata.orderBy || {}; } // if user specified a custom order then apply it diff --git a/src/query-builder/relation-count/RelationCountLoader.ts b/src/query-builder/relation-count/RelationCountLoader.ts index 77e615c2a..97801a679 100644 --- a/src/query-builder/relation-count/RelationCountLoader.ts +++ b/src/query-builder/relation-count/RelationCountLoader.ts @@ -33,8 +33,8 @@ export class RelationCountLoader { const relation = relationCountAttr.relation; // "category.posts" const inverseRelation = relation.inverseRelation; // "post.category" const referenceColumnName = inverseRelation.joinColumns[0].referencedColumn.propertyName; // post id - const inverseSideTable = relation.inverseEntityMetadata.table.target; // Post - const inverseSideTableName = relation.inverseEntityMetadata.table.name; // post + const inverseSideTable = relation.inverseEntityMetadata.target; // Post + const inverseSideTableName = relation.inverseEntityMetadata.tableName; // post const inverseSideTableAlias = relationCountAttr.alias || inverseSideTableName; // if condition (custom query builder factory) is set then relationIdAttr.alias defined const inverseSidePropertyName = inverseRelation.propertyName; // "category" from "post.category" @@ -100,9 +100,9 @@ export class RelationCountLoader { return { relationCountAttribute: relationCountAttr, results: [] }; const junctionAlias = relationCountAttr.junctionAlias; - const inverseSideTableName = relationCountAttr.joinInverseSideMetadata.table.name; + const inverseSideTableName = relationCountAttr.joinInverseSideMetadata.tableName; const inverseSideTableAlias = relationCountAttr.alias || inverseSideTableName; - const junctionTableName = relationCountAttr.relation.junctionEntityMetadata.table.name; + const junctionTableName = relationCountAttr.relation.junctionEntityMetadata.tableName; const condition = junctionAlias + "." + firstJunctionColumn.propertyName + " IN (" + referenceColumnValues + ")" + " AND " + junctionAlias + "." + secondJunctionColumn.propertyName + " = " + inverseSideTableAlias + "." + inverseJoinColumnName; diff --git a/src/query-builder/relation-id/RelationIdLoader.ts b/src/query-builder/relation-id/RelationIdLoader.ts index 4f121d771..4761d8f32 100644 --- a/src/query-builder/relation-id/RelationIdLoader.ts +++ b/src/query-builder/relation-id/RelationIdLoader.ts @@ -56,8 +56,8 @@ export class RelationIdLoader { const relation = relationIdAttr.relation; // "category.posts" const inverseRelation = relation.inverseRelation; // "post.category" const referenceColumnName = inverseRelation.joinColumns[0].referencedColumn.propertyName; // post id - const inverseSideTable = relation.inverseEntityMetadata.table.target; // Post - const inverseSideTableName = relation.inverseEntityMetadata.table.name; // post + const inverseSideTable = relation.inverseEntityMetadata.target; // Post + const inverseSideTableName = relation.inverseEntityMetadata.tableName; // post const inverseSideTableAlias = relationIdAttr.alias || inverseSideTableName; // if condition (custom query builder factory) is set then relationIdAttr.alias defined const inverseSidePropertyName = inverseRelation.propertyName; // "category" from "post.category" @@ -162,9 +162,9 @@ export class RelationIdLoader { return { relationIdAttribute: relationIdAttr, results: [] }; const junctionAlias = relationIdAttr.junctionAlias; - const inverseSideTableName = relationIdAttr.joinInverseSideMetadata.table.name; + const inverseSideTableName = relationIdAttr.joinInverseSideMetadata.tableName; const inverseSideTableAlias = relationIdAttr.alias || inverseSideTableName; - const junctionTableName = relationIdAttr.relation.junctionEntityMetadata.table.name; + const junctionTableName = relationIdAttr.relation.junctionEntityMetadata.tableName; const condition = junctionAlias + "." + firstJunctionColumn.propertyName + " IN (" + referenceColumnValues + ")" + " AND " + junctionAlias + "." + secondJunctionColumn.propertyName + " = " + inverseSideTableAlias + "." + inverseJoinColumnName; diff --git a/src/repository/MongoRepository.ts b/src/repository/MongoRepository.ts index bb5e36988..1ac3ddb82 100644 --- a/src/repository/MongoRepository.ts +++ b/src/repository/MongoRepository.ts @@ -9,36 +9,38 @@ import {DocumentToEntityTransformer} from "../query-builder/transformer/Document import {FindOneOptions} from "../find-options/FindOneOptions"; import {FindOptionsUtils} from "../find-options/FindOptionsUtils"; import { - Cursor, - Collection, - MongoCountPreferences, - CollectionAggregationOptions, AggregationCursor, - CollectionBluckWriteOptions, BulkWriteOpResultObject, - IndexOptions, + Code, + Collection, + CollectionAggregationOptions, + CollectionBluckWriteOptions, + CollectionInsertManyOptions, + CollectionInsertOneOptions, CollectionOptions, + CollStats, + CommandCursor, + Cursor, + CursorResult, DeleteWriteOpResultObject, FindAndModifyWriteOpResultObject, FindOneAndReplaceOption, GeoHaystackSearchOptions, GeoNearOptions, - ReadPreference, - Code, - OrderedBulkOperation, - UnorderedBulkOperation, - InsertWriteOpResult, - CollectionInsertManyOptions, - CollectionInsertOneOptions, + IndexOptions, InsertOneWriteOpResult, - CommandCursor, + InsertWriteOpResult, MapReduceOptions, + MongoCallback, + MongoCountPreferences, + MongoError, + OrderedBulkOperation, ParallelCollectionScanOptions, + ReadPreference, ReplaceOneOptions, - UpdateWriteOpResult, - CollStats, MongoCallback, MongoError, CursorResult + UnorderedBulkOperation, + UpdateWriteOpResult } from "mongodb"; -import {DeepPartial} from "../common/DeepPartial"; /** * Repository used to manage mongodb documents of a single entity type. @@ -110,7 +112,7 @@ export class MongoRepository extends Repository([ cursor.toArray(), - this.queryRunner.count(this.metadata.table.name, query), + this.queryRunner.count(this.metadata.tableName, query), ]); return [results, parseInt(count)]; } @@ -173,7 +175,7 @@ export class MongoRepository extends Repository { - return this.queryRunner.cursor(this.metadata.table.name, query); + return this.queryRunner.cursor(this.metadata.tableName, query); } /** @@ -227,28 +229,28 @@ export class MongoRepository extends Repository { - return this.queryRunner.aggregate(this.metadata.table.name, pipeline, options); + return this.queryRunner.aggregate(this.metadata.tableName, pipeline, options); } /** * Perform a bulkWrite operation without a fluent API. */ async bulkWrite(operations: ObjectLiteral[], options?: CollectionBluckWriteOptions): Promise { - return await this.queryRunner.bulkWrite(this.metadata.table.name, operations, options); + return await this.queryRunner.bulkWrite(this.metadata.tableName, operations, options); } /** * Count number of matching documents in the db to a query. */ async count(query?: ObjectLiteral, options?: MongoCountPreferences): Promise { - return await this.queryRunner.count(this.metadata.table.name, query || {}, options); + return await this.queryRunner.count(this.metadata.tableName, query || {}, options); } /** * Creates an index on the db and collection. */ async createCollectionIndex(fieldOrSpec: string|any, options?: IndexOptions): Promise { - return await this.queryRunner.createCollectionIndex(this.metadata.table.name, fieldOrSpec, options); + return await this.queryRunner.createCollectionIndex(this.metadata.tableName, fieldOrSpec, options); } /** @@ -257,154 +259,154 @@ export class MongoRepository extends Repository { - return await this.queryRunner.createCollectionIndexes(this.metadata.table.name, indexSpecs); + return await this.queryRunner.createCollectionIndexes(this.metadata.tableName, indexSpecs); } /** * Delete multiple documents on MongoDB. */ async deleteMany(query: ObjectLiteral, options?: CollectionOptions): Promise { - return await this.queryRunner.deleteMany(this.metadata.table.name, query, options); + return await this.queryRunner.deleteMany(this.metadata.tableName, query, options); } /** * Delete a document on MongoDB. */ async deleteOne(query: ObjectLiteral, options?: CollectionOptions): Promise { - return await this.queryRunner.deleteOne(this.metadata.table.name, query, options); + return await this.queryRunner.deleteOne(this.metadata.tableName, query, options); } /** * The distinct command returns returns a list of distinct values for the given key across a collection. */ async distinct(key: string, query: ObjectLiteral, options?: { readPreference?: ReadPreference|string }): Promise { - return await this.queryRunner.distinct(this.metadata.table.name, key, query, options); + return await this.queryRunner.distinct(this.metadata.tableName, key, query, options); } /** * Drops an index from this collection. */ async dropCollectionIndex(indexName: string, options?: CollectionOptions): Promise { - return await this.queryRunner.dropCollectionIndex(this.metadata.table.name, indexName, options); + return await this.queryRunner.dropCollectionIndex(this.metadata.tableName, indexName, options); } /** * Drops all indexes from the collection. */ async dropCollectionIndexes(): Promise { - return await this.queryRunner.dropCollectionIndexes(this.metadata.table.name); + return await this.queryRunner.dropCollectionIndexes(this.metadata.tableName); } /** * Find a document and delete it in one atomic operation, requires a write lock for the duration of the operation. */ async findOneAndDelete(query: ObjectLiteral, options?: { projection?: Object, sort?: Object, maxTimeMS?: number }): Promise { - return await this.queryRunner.findOneAndDelete(this.metadata.table.name, query, options); + return await this.queryRunner.findOneAndDelete(this.metadata.tableName, query, options); } /** * Find a document and replace it in one atomic operation, requires a write lock for the duration of the operation. */ async findOneAndReplace(query: ObjectLiteral, replacement: Object, options?: FindOneAndReplaceOption): Promise { - return await this.queryRunner.findOneAndReplace(this.metadata.table.name, query, replacement, options); + return await this.queryRunner.findOneAndReplace(this.metadata.tableName, query, replacement, options); } /** * Find a document and update it in one atomic operation, requires a write lock for the duration of the operation. */ async findOneAndUpdate(query: ObjectLiteral, update: Object, options?: FindOneAndReplaceOption): Promise { - return await this.queryRunner.findOneAndUpdate(this.metadata.table.name, query, update, options); + return await this.queryRunner.findOneAndUpdate(this.metadata.tableName, query, update, options); } /** * Execute a geo search using a geo haystack index on a collection. */ async geoHaystackSearch(x: number, y: number, options?: GeoHaystackSearchOptions): Promise { - return await this.queryRunner.geoHaystackSearch(this.metadata.table.name, x, y, options); + return await this.queryRunner.geoHaystackSearch(this.metadata.tableName, x, y, options); } /** * Execute the geoNear command to search for items in the collection. */ async geoNear(x: number, y: number, options?: GeoNearOptions): Promise { - return await this.queryRunner.geoNear(this.metadata.table.name, x, y, options); + return await this.queryRunner.geoNear(this.metadata.tableName, x, y, options); } /** * Run a group command across a collection. */ async group(keys: Object|Array|Function|Code, condition: Object, initial: Object, reduce: Function|Code, finalize: Function|Code, command: boolean, options?: { readPreference?: ReadPreference | string }): Promise { - return await this.queryRunner.group(this.metadata.table.name, keys, condition, initial, reduce, finalize, command, options); + return await this.queryRunner.group(this.metadata.tableName, keys, condition, initial, reduce, finalize, command, options); } /** * Retrieve all the indexes on the collection. */ async collectionIndexes(): Promise { - return await this.queryRunner.collectionIndexes(this.metadata.table.name); + return await this.queryRunner.collectionIndexes(this.metadata.tableName); } /** * Retrieve all the indexes on the collection. */ async collectionIndexExists(indexes: string|string[]): Promise { - return await this.queryRunner.collectionIndexExists(this.metadata.table.name, indexes); + return await this.queryRunner.collectionIndexExists(this.metadata.tableName, indexes); } /** * Retrieves this collections index info. */ async collectionIndexInformation(options?: { full: boolean }): Promise { - return await this.queryRunner.collectionIndexInformation(this.metadata.table.name, options); + return await this.queryRunner.collectionIndexInformation(this.metadata.tableName, options); } /** * Initiate an In order bulk write operation, operations will be serially executed in the order they are added, creating a new operation for each switch in types. */ initializeOrderedBulkOp(options?: CollectionOptions): OrderedBulkOperation { - return this.queryRunner.initializeOrderedBulkOp(this.metadata.table.name, options); + return this.queryRunner.initializeOrderedBulkOp(this.metadata.tableName, options); } /** * Initiate a Out of order batch write operation. All operations will be buffered into insert/update/remove commands executed out of order. */ initializeUnorderedBulkOp(options?: CollectionOptions): UnorderedBulkOperation { - return this.queryRunner.initializeUnorderedBulkOp(this.metadata.table.name, options); + return this.queryRunner.initializeUnorderedBulkOp(this.metadata.tableName, options); } /** * Inserts an array of documents into MongoDB. */ async insertMany(docs: ObjectLiteral[], options?: CollectionInsertManyOptions): Promise { - return await this.queryRunner.insertMany(this.metadata.table.name, docs, options); + return await this.queryRunner.insertMany(this.metadata.tableName, docs, options); } /** * Inserts a single document into MongoDB. */ async insertOne(doc: ObjectLiteral, options?: CollectionInsertOneOptions): Promise { - return await this.queryRunner.insertOne(this.metadata.table.name, doc, options); + return await this.queryRunner.insertOne(this.metadata.tableName, doc, options); } /** * Returns if the collection is a capped collection. */ async isCapped(): Promise { - return await this.queryRunner.isCapped(this.metadata.table.name); + return await this.queryRunner.isCapped(this.metadata.tableName); } /** * Get the list of all indexes information for the collection. */ listCollectionIndexes(options?: { batchSize?: number, readPreference?: ReadPreference|string }): CommandCursor { - return this.queryRunner.listCollectionIndexes(this.metadata.table.name, options); + return this.queryRunner.listCollectionIndexes(this.metadata.tableName, options); } /** * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection. */ async mapReduce(map: Function|string, reduce: Function|string, options?: MapReduceOptions): Promise { - return await this.queryRunner.mapReduce(this.metadata.table.name, map, reduce, options); + return await this.queryRunner.mapReduce(this.metadata.tableName, map, reduce, options); } /** @@ -412,49 +414,49 @@ export class MongoRepository extends Repository[]> { - return await this.queryRunner.parallelCollectionScan(this.metadata.table.name, options); + return await this.queryRunner.parallelCollectionScan(this.metadata.tableName, options); } /** * Reindex all indexes on the collection Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. */ async reIndex(): Promise { - return await this.queryRunner.reIndex(this.metadata.table.name); + return await this.queryRunner.reIndex(this.metadata.tableName); } /** * Reindex all indexes on the collection Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. */ async rename(newName: string, options?: { dropTarget?: boolean }): Promise { - return await this.queryRunner.rename(this.metadata.table.name, newName, options); + return await this.queryRunner.rename(this.metadata.tableName, newName, options); } /** * Replace a document on MongoDB. */ async replaceOne(query: ObjectLiteral, doc: ObjectLiteral, options?: ReplaceOneOptions): Promise { - return await this.queryRunner.replaceOne(this.metadata.table.name, query, doc, options); + return await this.queryRunner.replaceOne(this.metadata.tableName, query, doc, options); } /** * Get all the collection statistics. */ async stats(options?: { scale: number }): Promise { - return await this.queryRunner.stats(this.metadata.table.name, options); + return await this.queryRunner.stats(this.metadata.tableName, options); } /** * Update multiple documents on MongoDB. */ async updateMany(query: ObjectLiteral, update: ObjectLiteral, options?: { upsert?: boolean, w?: any, wtimeout?: number, j?: boolean }): Promise { - return await this.queryRunner.updateMany(this.metadata.table.name, query, update, options); + return await this.queryRunner.updateMany(this.metadata.tableName, query, update, options); } /** * Update a single document on MongoDB. */ async updateOne(query: ObjectLiteral, update: ObjectLiteral, options?: ReplaceOneOptions): Promise { - return await this.queryRunner.updateOne(this.metadata.table.name, query, update, options); + return await this.queryRunner.updateOne(this.metadata.tableName, query, update, options); } // ------------------------------------------------------------------------- diff --git a/src/repository/Repository.ts b/src/repository/Repository.ts index 8e3277164..9fc541133 100644 --- a/src/repository/Repository.ts +++ b/src/repository/Repository.ts @@ -279,7 +279,7 @@ export class Repository { * Counts entities that match given find options or conditions. */ count(optionsOrConditions?: FindManyOptions|DeepPartial): Promise { - const qb = this.createQueryBuilder(FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || this.metadata.table.name); + const qb = this.createQueryBuilder(FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || this.metadata.tableName); return FindOptionsUtils.applyFindManyOptionsOrConditionsToQueryBuilder(qb, optionsOrConditions).getCount(); } @@ -297,7 +297,7 @@ export class Repository { * Finds entities that match given find options or conditions. */ find(optionsOrConditions?: FindManyOptions|DeepPartial): Promise { - const qb = this.createQueryBuilder(FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || this.metadata.table.name); + const qb = this.createQueryBuilder(FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || this.metadata.tableName); return FindOptionsUtils.applyFindManyOptionsOrConditionsToQueryBuilder(qb, optionsOrConditions).getMany(); } @@ -321,7 +321,7 @@ export class Repository { * but ignores pagination settings (from and take options). */ findAndCount(optionsOrConditions?: FindManyOptions|DeepPartial): Promise<[ Entity[], number ]> { - const qb = this.createQueryBuilder(FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || this.metadata.table.name); + const qb = this.createQueryBuilder(FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || this.metadata.tableName); return FindOptionsUtils.applyFindManyOptionsOrConditionsToQueryBuilder(qb, optionsOrConditions).getManyAndCount(); } @@ -342,7 +342,7 @@ export class Repository { * Optionally find options can be applied. */ findByIds(ids: any[], optionsOrConditions?: FindManyOptions|DeepPartial): Promise { - const qb = this.createQueryBuilder(FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || this.metadata.table.name); + const qb = this.createQueryBuilder(FindOptionsUtils.extractFindManyOptionsAlias(optionsOrConditions) || this.metadata.tableName); return FindOptionsUtils.applyFindManyOptionsOrConditionsToQueryBuilder(qb, optionsOrConditions) .andWhereInIds(ids) .getMany(); @@ -362,7 +362,7 @@ export class Repository { * Finds first entity that matches given conditions. */ findOne(optionsOrConditions?: FindOneOptions|DeepPartial): Promise { - const qb = this.createQueryBuilder(FindOptionsUtils.extractFindOneOptionsAlias(optionsOrConditions) || this.metadata.table.name); + const qb = this.createQueryBuilder(FindOptionsUtils.extractFindOneOptionsAlias(optionsOrConditions) || this.metadata.tableName); return FindOptionsUtils.applyFindOneOptionsOrConditionsToQueryBuilder(qb, optionsOrConditions).getOne(); } @@ -383,7 +383,7 @@ export class Repository { * Optionally find options or conditions can be applied. */ findOneById(id: any, optionsOrConditions?: FindOneOptions|DeepPartial): Promise { - const qb = this.createQueryBuilder(FindOptionsUtils.extractFindOneOptionsAlias(optionsOrConditions) || this.metadata.table.name); + const qb = this.createQueryBuilder(FindOptionsUtils.extractFindOneOptionsAlias(optionsOrConditions) || this.metadata.tableName); return FindOptionsUtils.applyFindOneOptionsOrConditionsToQueryBuilder(qb, optionsOrConditions) .andWhereInIds([id]) .getOne(); @@ -451,7 +451,7 @@ export class Repository { const queryRunnerProvider = this.queryRunnerProvider || new QueryRunnerProvider(this.connection.driver); const queryRunner = await queryRunnerProvider.provide(); try { - return await queryRunner.truncate(this.metadata.table.name); // await is needed here because we are using finally + return await queryRunner.truncate(this.metadata.tableName); // await is needed here because we are using finally } finally { await queryRunnerProvider.release(queryRunner); diff --git a/src/repository/RepositoryAggregator.ts b/src/repository/RepositoryAggregator.ts index 43ce9c9b5..73b42b4f3 100644 --- a/src/repository/RepositoryAggregator.ts +++ b/src/repository/RepositoryAggregator.ts @@ -45,7 +45,7 @@ export class RepositoryAggregator { const factory = getFromContainer(RepositoryFactory); - if (metadata.table.isClosure) { + if (metadata.isClosure) { this.repository = this.treeRepository = factory.createTreeRepository(connection, metadata, queryRunnerProvider); } else { this.repository = factory.createRepository(connection, metadata, queryRunnerProvider); diff --git a/src/repository/SpecificRepository.ts b/src/repository/SpecificRepository.ts index 09dea5308..949f5e21c 100644 --- a/src/repository/SpecificRepository.ts +++ b/src/repository/SpecificRepository.ts @@ -61,11 +61,11 @@ export class SpecificRepository { let table: string, values: any = {}, conditions: any = {}; if (relation.isOwning) { - table = relation.entityMetadata.table.name; + table = relation.entityMetadata.tableName; values[relation.name] = relatedEntityId; conditions[relation.joinColumns[0].referencedColumn.fullName] = entityId; } else { - table = relation.inverseEntityMetadata.table.name; + table = relation.inverseEntityMetadata.tableName; values[relation.inverseRelation.name] = relatedEntityId; conditions[relation.inverseRelation.joinColumns[0].referencedColumn.fullName] = entityId; } @@ -112,11 +112,11 @@ export class SpecificRepository { let table: string, values: any = {}, conditions: any = {}; if (relation.isOwning) { - table = relation.inverseEntityMetadata.table.name; + table = relation.inverseEntityMetadata.tableName; values[relation.inverseRelation.name] = relatedEntityId; conditions[relation.inverseRelation.joinColumns[0].referencedColumn.fullName] = entityId; } else { - table = relation.entityMetadata.table.name; + table = relation.entityMetadata.tableName; values[relation.name] = relatedEntityId; conditions[relation.joinColumns[0].referencedColumn.fullName] = entityId; } @@ -168,7 +168,7 @@ export class SpecificRepository { values[relation.junctionEntityMetadata.columns[0].fullName] = relatedEntityId; } - return queryRunner.insert(relation.junctionEntityMetadata.table.name, values); + return queryRunner.insert(relation.junctionEntityMetadata.tableName, values); }); await Promise.all(insertPromises); @@ -218,7 +218,7 @@ export class SpecificRepository { values[relation.junctionEntityMetadata.columns[0].fullName] = relatedEntityId; } - return queryRunner.insert(relation.junctionEntityMetadata.table.name, values); + return queryRunner.insert(relation.junctionEntityMetadata.tableName, values); }); await Promise.all(insertPromises); @@ -262,7 +262,7 @@ export class SpecificRepository { const qb = new QueryBuilder(this.connection, this.queryRunnerProvider) .delete() - .fromTable(relation.junctionEntityMetadata.table.name, "junctionEntity"); + .fromTable(relation.junctionEntityMetadata.tableName, "junctionEntity"); const firstColumnName = this.connection.driver.escapeColumnName(relation.isOwning ? relation.junctionEntityMetadata.columns[0].fullName : relation.junctionEntityMetadata.columns[1].fullName); const secondColumnName = this.connection.driver.escapeColumnName(relation.isOwning ? relation.junctionEntityMetadata.columns[1].fullName : relation.junctionEntityMetadata.columns[0].fullName); @@ -311,7 +311,7 @@ export class SpecificRepository { const qb = new QueryBuilder(this.connection, this.queryRunnerProvider) .delete() - .from(relation.junctionEntityMetadata.table.name, "junctionEntity"); + .from(relation.junctionEntityMetadata.tableName, "junctionEntity"); const firstColumnName = relation.isOwning ? relation.junctionEntityMetadata.columns[1].fullName : relation.junctionEntityMetadata.columns[0].fullName; const secondColumnName = relation.isOwning ? relation.junctionEntityMetadata.columns[0].fullName : relation.junctionEntityMetadata.columns[1].fullName; @@ -381,7 +381,7 @@ export class SpecificRepository { * Note that event listeners and event subscribers won't work (and will not send any events) when using this operation. */ async removeById(id: any): Promise { - const alias = this.metadata.table.name; + const alias = this.metadata.tableName; const parameters: ObjectLiteral = {}; let condition = ""; @@ -408,7 +408,7 @@ export class SpecificRepository { * Note that event listeners and event subscribers won't work (and will not send any events) when using this operation. */ async removeByIds(ids: any[]): Promise { - const alias = this.metadata.table.name; + const alias = this.metadata.tableName; const parameters: ObjectLiteral = {}; let condition = ""; @@ -464,7 +464,7 @@ export class SpecificRepository { inverseEntityColumnNames.forEach(columnName => { qb.select(ea("junction") + "." + ec(columnName) + " AS " + ea(columnName)); }); - qb.fromTable(relation.junctionEntityMetadata.table.name, "junction"); + qb.fromTable(relation.junctionEntityMetadata.tableName, "junction"); Object.keys(entityId).forEach((columnName) => { const junctionColumnName = ownerEntityColumns.find(joinColumn => joinColumn.referencedColumn.name === columnName); qb.andWhere(ea("junction") + "." + ec(junctionColumnName!.name) + "=:" + junctionColumnName!.name + "_entityId", {[junctionColumnName!.name + "_entityId"]: entityId[columnName]}); diff --git a/src/repository/TreeRepository.ts b/src/repository/TreeRepository.ts index 15e86e6ca..acd822ef5 100644 --- a/src/repository/TreeRepository.ts +++ b/src/repository/TreeRepository.ts @@ -49,7 +49,7 @@ export class TreeRepository extends Repository { const joinCondition = `${escapeAlias(alias)}.${escapeColumn(this.metadata.firstPrimaryColumn.fullName)}=${escapeAlias(closureTableAlias)}.${escapeColumn("descendant")}`; return this.createQueryBuilder(alias) - .innerJoin(this.metadata.closureJunctionTable.table.name, closureTableAlias, joinCondition) + .innerJoin(this.metadata.closureJunctionTable.tableName, closureTableAlias, joinCondition) .where(`${escapeAlias(closureTableAlias)}.${escapeColumn("ancestor")}=${this.metadata.getEntityIdMap(entity)![this.metadata.firstPrimaryColumn.propertyName]}`); } @@ -97,7 +97,7 @@ export class TreeRepository extends Repository { const joinCondition = `${escapeAlias(alias)}.${escapeColumn(this.metadata.firstPrimaryColumn.fullName)}=${escapeAlias(closureTableAlias)}.${escapeColumn("ancestor")}`; return this.createQueryBuilder(alias) - .innerJoin(this.metadata.closureJunctionTable.table.name, closureTableAlias, joinCondition) + .innerJoin(this.metadata.closureJunctionTable.tableName, closureTableAlias, joinCondition) .where(`${escapeAlias(closureTableAlias)}.${escapeColumn("descendant")}=${this.metadata.getEntityIdMap(entity)![this.metadata.firstPrimaryColumn.propertyName]}`); } diff --git a/src/schema-builder/SchemaBuilder.ts b/src/schema-builder/SchemaBuilder.ts index 7f1470e55..8b017c440 100644 --- a/src/schema-builder/SchemaBuilder.ts +++ b/src/schema-builder/SchemaBuilder.ts @@ -94,14 +94,14 @@ export class SchemaBuilder { // ------------------------------------------------------------------------- protected get entityToSyncMetadatas(): EntityMetadata[] { - return this.entityMetadatas.filter(metadata => !metadata.table.skipSchemaSync); + return this.entityMetadatas.filter(metadata => !metadata.skipSchemaSync); } /** * Loads all table schemas from the database. */ protected loadTableSchemas(): Promise { - const tableNames = this.entityToSyncMetadatas.map(metadata => metadata.table.name); + const tableNames = this.entityToSyncMetadatas.map(metadata => metadata.tableName); return this.queryRunner.loadTableSchemas(tableNames); } @@ -111,7 +111,7 @@ export class SchemaBuilder { protected async dropOldForeignKeys(): Promise { await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { - const tableSchema = this.tableSchemas.find(table => table.name === metadata.table.name); + const tableSchema = this.tableSchemas.find(table => table.name === metadata.tableName); if (!tableSchema) return; @@ -140,14 +140,14 @@ export class SchemaBuilder { protected async createNewTables(): Promise { await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { // check if table does not exist yet - const existTableSchema = this.tableSchemas.find(table => table.name === metadata.table.name); + const existTableSchema = this.tableSchemas.find(table => table.name === metadata.tableName); if (existTableSchema) return; - this.logger.logSchemaBuild(`creating a new table: ${metadata.table.name}`); + this.logger.logSchemaBuild(`creating a new table: ${metadata.tableName}`); // create a new table schema and sync it in the database - const tableSchema = new TableSchema(metadata.table.name, this.metadataColumnsToColumnSchemas(metadata.columns), true); + const tableSchema = new TableSchema(metadata.tableName, this.metadataColumnsToColumnSchemas(metadata.columns), true); this.tableSchemas.push(tableSchema); await this.queryRunner.createTable(tableSchema); }); @@ -159,7 +159,7 @@ export class SchemaBuilder { */ protected dropRemovedColumns() { return PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { - const tableSchema = this.tableSchemas.find(table => table.name === metadata.table.name); + const tableSchema = this.tableSchemas.find(table => table.name === metadata.tableName); if (!tableSchema) return; // find columns that exist in the database but does not exist in the metadata @@ -171,12 +171,12 @@ export class SchemaBuilder { // drop all foreign keys that has column to be removed in its columns await Promise.all(droppedColumnSchemas.map(droppedColumnSchema => { - return this.dropColumnReferencedForeignKeys(metadata.table.name, droppedColumnSchema.name); + return this.dropColumnReferencedForeignKeys(metadata.tableName, droppedColumnSchema.name); })); // drop all indices that point to this column await Promise.all(droppedColumnSchemas.map(droppedColumnSchema => { - return this.dropColumnReferencedIndices(metadata.table.name, droppedColumnSchema.name); + return this.dropColumnReferencedIndices(metadata.tableName, droppedColumnSchema.name); })); this.logger.logSchemaBuild(`columns dropped in ${tableSchema.name}: ` + droppedColumnSchemas.map(column => column.name).join(", ")); @@ -196,7 +196,7 @@ export class SchemaBuilder { */ protected addNewColumns() { return PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { - const tableSchema = this.tableSchemas.find(table => table.name === metadata.table.name); + const tableSchema = this.tableSchemas.find(table => table.name === metadata.tableName); if (!tableSchema) return; @@ -222,7 +222,7 @@ export class SchemaBuilder { */ protected updateExistColumns() { return PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { - const tableSchema = this.tableSchemas.find(table => table.name === metadata.table.name); + const tableSchema = this.tableSchemas.find(table => table.name === metadata.tableName); if (!tableSchema) return; @@ -235,7 +235,7 @@ export class SchemaBuilder { // drop all foreign keys that point to this column const dropRelatedForeignKeysPromises = updatedColumnSchemas .filter(changedColumnSchema => !!metadata.columns.find(columnMetadata => columnMetadata.fullName === changedColumnSchema.name)) - .map(changedColumnSchema => this.dropColumnReferencedForeignKeys(metadata.table.name, changedColumnSchema.name)); + .map(changedColumnSchema => this.dropColumnReferencedForeignKeys(metadata.tableName, changedColumnSchema.name)); // wait until all related foreign keys are dropped await Promise.all(dropRelatedForeignKeysPromises); @@ -243,7 +243,7 @@ export class SchemaBuilder { // drop all indices that point to this column const dropRelatedIndicesPromises = updatedColumnSchemas .filter(changedColumnSchema => !!metadata.columns.find(columnMetadata => columnMetadata.fullName === changedColumnSchema.name)) - .map(changedColumnSchema => this.dropColumnReferencedIndices(metadata.table.name, changedColumnSchema.name)); + .map(changedColumnSchema => this.dropColumnReferencedIndices(metadata.tableName, changedColumnSchema.name)); // wait until all related indices are dropped await Promise.all(dropRelatedIndicesPromises); @@ -269,7 +269,7 @@ export class SchemaBuilder { */ protected updatePrimaryKeys() { return PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { - const tableSchema = this.tableSchemas.find(table => table.name === metadata.table.name && !table.justCreated); + const tableSchema = this.tableSchemas.find(table => table.name === metadata.tableName && !table.justCreated); if (!tableSchema) return; @@ -299,7 +299,7 @@ export class SchemaBuilder { */ protected createForeignKeys() { return PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { - const tableSchema = this.tableSchemas.find(table => table.name === metadata.table.name); + const tableSchema = this.tableSchemas.find(table => table.name === metadata.tableName); if (!tableSchema) return; @@ -323,7 +323,7 @@ export class SchemaBuilder { protected createIndices() { // return Promise.all(this.entityMetadatas.map(metadata => this.createIndices(metadata.table, metadata.indices))); return PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { - const tableSchema = this.tableSchemas.find(table => table.name === metadata.table.name); + const tableSchema = this.tableSchemas.find(table => table.name === metadata.tableName); if (!tableSchema) return; @@ -333,7 +333,7 @@ export class SchemaBuilder { .map(async indexSchema => { this.logger.logSchemaBuild(`dropping an index: ${indexSchema.name}`); tableSchema.removeIndex(indexSchema); - await this.queryRunner.dropIndex(metadata.table.name, indexSchema.name); + await this.queryRunner.dropIndex(metadata.tableName, indexSchema.name); }); // then create table indices for all composite indices we have diff --git a/src/schema-builder/schema/IndexSchema.ts b/src/schema-builder/schema/IndexSchema.ts index a3c6110b5..8e5ba8d2a 100644 --- a/src/schema-builder/schema/IndexSchema.ts +++ b/src/schema-builder/schema/IndexSchema.ts @@ -60,7 +60,7 @@ export class IndexSchema { */ static create(indexMetadata: IndexMetadata): IndexSchema { return new IndexSchema( - indexMetadata.entityMetadata.table.name, + indexMetadata.entityMetadata.tableName, indexMetadata.name, indexMetadata.columns, indexMetadata.isUnique diff --git a/src/schema-builder/schema/TableSchema.ts b/src/schema-builder/schema/TableSchema.ts index e20cf0283..661d86e60 100644 --- a/src/schema-builder/schema/TableSchema.ts +++ b/src/schema-builder/schema/TableSchema.ts @@ -223,7 +223,7 @@ export class TableSchema { * todo: need deeper implementation */ static create(entityMetadata: EntityMetadata, queryRunner: QueryRunner) { - const tableSchema = new TableSchema(entityMetadata.table.name); + const tableSchema = new TableSchema(entityMetadata.tableName); entityMetadata.columns.forEach(column => { tableSchema.columns.push(ColumnSchema.create(column, queryRunner.normalizeType(column))); }); diff --git a/test/functional/connection/connection.ts b/test/functional/connection/connection.ts index 898c639cd..9d7711c83 100644 --- a/test/functional/connection/connection.ts +++ b/test/functional/connection/connection.ts @@ -3,7 +3,7 @@ import {expect} from "chai"; import {Post} from "./entity/Post"; import {View} from "./entity/View"; import {Category} from "./entity/Category"; -import {createTestingConnections, closeTestingConnections, setupSingleTestingConnection} from "../../utils/test-utils"; +import {closeTestingConnections, createTestingConnections, setupSingleTestingConnection} from "../../utils/test-utils"; import {Connection} from "../../../src/connection/Connection"; import {Repository} from "../../../src/repository/Repository"; import {TreeRepository} from "../../../src/repository/TreeRepository"; @@ -340,7 +340,7 @@ describe("Connection", () => { connection.importNamingStrategies([FirstCustomNamingStrategy]); connection.useNamingStrategy(FirstCustomNamingStrategy); await connection.connect(); - connection.getMetadata(Post).table.name.should.be.equal("POST"); + connection.getMetadata(Post).tableName.should.be.equal("POST"); }); it("should use naming strategy when its name passed to useNamingStrategy method", async () => { @@ -348,7 +348,7 @@ describe("Connection", () => { connection.importNamingStrategies([SecondCustomNamingStrategy]); connection.useNamingStrategy("secondCustomNamingStrategy"); await connection.connect(); - connection.getMetadata(Category).table.name.should.be.equal("category"); + connection.getMetadata(Category).tableName.should.be.equal("category"); }); it("should throw an error if not registered naming strategy was used (assert by name)", () => {