removed table metadata

This commit is contained in:
Zotov Dmitry 2017-05-02 12:17:09 +05:00
parent 77b177e0ab
commit d401b4f3ed
29 changed files with 336 additions and 502 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
});
}*/
}

View File

@ -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

View File

@ -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 => {

View File

@ -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;
}
}

View File

@ -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);
}
/**

View File

@ -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;
}
/**

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -300,7 +300,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
// 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<Entity extends ObjectLiteral> {
databaseEntities = await this.connection
.getRepository<ObjectLiteral>(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<Entity extends ObjectLiteral> {
databaseEntities = await this.connection
.getRepository<ObjectLiteral>(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();

View File

@ -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<void> {
// 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);

View File

@ -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;

View File

@ -214,7 +214,7 @@ export class QueryBuilder<Entity> {
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<Entity> {
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<Entity> {
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<Entity> {
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<Entity> {
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<Entity> {
// 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<Entity> {
// 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

View File

@ -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;

View File

@ -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;

View File

@ -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<Entity extends ObjectLiteral> extends Repository<En
}
const [results, count] = await Promise.all<any>([
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<Entity extends ObjectLiteral> extends Repository<En
* Creates a cursor for a query that can be used to iterate over results from MongoDB.
*/
createCursor(query?: ObjectLiteral): Cursor<Entity> {
return this.queryRunner.cursor(this.metadata.table.name, query);
return this.queryRunner.cursor(this.metadata.tableName, query);
}
/**
@ -227,28 +229,28 @@ export class MongoRepository<Entity extends ObjectLiteral> extends Repository<En
* Execute an aggregation framework pipeline against the collection.
*/
aggregate(pipeline: ObjectLiteral[], options?: CollectionAggregationOptions): AggregationCursor<Entity> {
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<BulkWriteOpResultObject> {
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<any> {
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<string> {
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<Entity extends ObjectLiteral> extends Repository<En
* Index specifications are defined at http://docs.mongodb.org/manual/reference/command/createIndexes/.
*/
async createCollectionIndexes(indexSpecs: ObjectLiteral[]): Promise<void> {
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<DeleteWriteOpResultObject> {
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<DeleteWriteOpResultObject> {
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<any> {
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<any> {
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<any> {
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<FindAndModifyWriteOpResultObject> {
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<FindAndModifyWriteOpResultObject> {
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<FindAndModifyWriteOpResultObject> {
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<any> {
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<any> {
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<any>|Function|Code, condition: Object, initial: Object, reduce: Function|Code, finalize: Function|Code, command: boolean, options?: { readPreference?: ReadPreference | string }): Promise<any> {
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<any> {
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<boolean> {
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<any> {
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<InsertWriteOpResult> {
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<InsertOneWriteOpResult> {
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<any> {
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<any> {
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<Entity extends ObjectLiteral> extends Repository<En
* There are no ordering guarantees for returned results.
*/
async parallelCollectionScan(options?: ParallelCollectionScanOptions): Promise<Cursor<Entity>[]> {
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<any> {
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<Collection> {
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<UpdateWriteOpResult> {
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<CollStats> {
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<UpdateWriteOpResult> {
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<UpdateWriteOpResult> {
return await this.queryRunner.updateOne(this.metadata.table.name, query, update, options);
return await this.queryRunner.updateOne(this.metadata.tableName, query, update, options);
}
// -------------------------------------------------------------------------

View File

@ -279,7 +279,7 @@ export class Repository<Entity extends ObjectLiteral> {
* Counts entities that match given find options or conditions.
*/
count(optionsOrConditions?: FindManyOptions<Entity>|DeepPartial<Entity>): Promise<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).getCount();
}
@ -297,7 +297,7 @@ export class Repository<Entity extends ObjectLiteral> {
* Finds entities that match given find options or conditions.
*/
find(optionsOrConditions?: FindManyOptions<Entity>|DeepPartial<Entity>): Promise<Entity[]> {
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<Entity extends ObjectLiteral> {
* but ignores pagination settings (from and take options).
*/
findAndCount(optionsOrConditions?: FindManyOptions<Entity>|DeepPartial<Entity>): 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<Entity extends ObjectLiteral> {
* Optionally find options can be applied.
*/
findByIds(ids: any[], optionsOrConditions?: FindManyOptions<Entity>|DeepPartial<Entity>): Promise<Entity[]> {
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<Entity extends ObjectLiteral> {
* Finds first entity that matches given conditions.
*/
findOne(optionsOrConditions?: FindOneOptions<Entity>|DeepPartial<Entity>): Promise<Entity|undefined> {
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<Entity extends ObjectLiteral> {
* Optionally find options or conditions can be applied.
*/
findOneById(id: any, optionsOrConditions?: FindOneOptions<Entity>|DeepPartial<Entity>): Promise<Entity|undefined> {
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<Entity extends ObjectLiteral> {
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);

View File

@ -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);

View File

@ -61,11 +61,11 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
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<Entity extends ObjectLiteral> {
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<Entity extends ObjectLiteral> {
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<Entity extends ObjectLiteral> {
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<Entity extends ObjectLiteral> {
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<Entity extends ObjectLiteral> {
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<Entity extends ObjectLiteral> {
* 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<void> {
const alias = this.metadata.table.name;
const alias = this.metadata.tableName;
const parameters: ObjectLiteral = {};
let condition = "";
@ -408,7 +408,7 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
* 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<void> {
const alias = this.metadata.table.name;
const alias = this.metadata.tableName;
const parameters: ObjectLiteral = {};
let condition = "";
@ -464,7 +464,7 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
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]});

View File

@ -49,7 +49,7 @@ export class TreeRepository<Entity> extends Repository<Entity> {
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<Entity> extends Repository<Entity> {
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]}`);
}

View File

@ -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<TableSchema[]> {
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<void> {
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<void> {
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

View File

@ -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

View File

@ -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)));
});

View File

@ -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)", () => {