replaced foreignKey.columns back to joinColumns

This commit is contained in:
Zotov Dmitry 2017-04-28 17:17:23 +05:00
parent cb939ef529
commit 569dcf28c5
11 changed files with 80 additions and 48 deletions

View File

@ -35,7 +35,7 @@ export class LazyRelationsWrapper {
if (relation.isManyToOne || relation.isOneToOneOwner) {
const joinColumns = relation.isOwning ? relation.foreignKey.columns : relation.inverseRelation.foreignKey.columns;
const joinColumns = relation.isOwning ? relation.joinColumns : relation.inverseRelation.joinColumns;
const conditions = joinColumns.map(joinColumn => {
return `${relation.entityMetadata.name}.${relation.propertyName} = ${relation.propertyName}.${joinColumn.referencedColumn.propertyName}`;
}).join(" AND ");
@ -74,7 +74,7 @@ export class LazyRelationsWrapper {
qb.select(relation.propertyName)
.from(relation.inverseRelation.entityMetadata.target, relation.propertyName);
relation.inverseRelation.foreignKey.columns.forEach(joinColumn => {
relation.inverseRelation.joinColumns.forEach(joinColumn => {
qb.andWhere(`${relation.propertyName}.${joinColumn.propertyName} = :${joinColumn.referencedColumn.propertyName}`)
.setParameter(`${joinColumn.referencedColumn.propertyName}`, this[joinColumn.referencedColumn.propertyName]);
});

View File

@ -269,7 +269,7 @@ export class EntityMetadataBuilder {
);
foreignKey.entityMetadata = relation.entityMetadata;
relation.foreignKey = foreignKey;
relation.foreignKeys = [foreignKey];
relation.entityMetadata.foreignKeys.push(foreignKey);
});
});

View File

@ -603,12 +603,12 @@ export class EntityMetadata {
// if entity id is a relation, then extract referenced column from that relation
const columnRelation = this.relations.find(relation => relation.propertyName === column.propertyName);
if (columnRelation && columnRelation.foreignKey.columns.length) {
const ids = columnRelation.foreignKey.columns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
if (columnRelation && columnRelation.joinColumns.length) {
const ids = columnRelation.joinColumns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
map[column.propertyName] = ids.length === 1 ? ids[0] : ids;
} else if (columnRelation && columnRelation.inverseRelation.foreignKey.columns.length) {
const ids = columnRelation.inverseRelation.foreignKey.columns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
} else if (columnRelation && columnRelation.inverseRelation.joinColumns.length) {
const ids = columnRelation.inverseRelation.joinColumns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
map[column.propertyName] = ids.length === 1 ? ids[0] : ids;
} else {
@ -626,12 +626,12 @@ export class EntityMetadata {
// if entity id is a relation, then extract referenced column from that relation
const columnRelation = this.relations.find(relation => relation.propertyName === column.propertyName);
if (columnRelation && columnRelation.foreignKey.columns.length) {
const ids = columnRelation.foreignKey.columns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
if (columnRelation && columnRelation.joinColumns.length) {
const ids = columnRelation.joinColumns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
map[column.propertyName] = ids.length === 1 ? ids[0] : ids;
} else if (columnRelation && columnRelation.inverseRelation.foreignKey.columns.length) {
const ids = columnRelation.inverseRelation.foreignKey.columns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
} else if (columnRelation && columnRelation.inverseRelation.joinColumns.length) {
const ids = columnRelation.inverseRelation.joinColumns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
map[column.propertyName] = ids.length === 1 ? ids[0] : ids;
} else {
@ -656,12 +656,12 @@ export class EntityMetadata {
// if entity id is a relation, then extract referenced column from that relation
const columnRelation = this.relations.find(relation => relation.propertyName === column.propertyName);
if (columnRelation && columnRelation.foreignKey.columns.length) {
const ids = columnRelation.foreignKey.columns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
if (columnRelation && columnRelation.joinColumns.length) {
const ids = columnRelation.joinColumns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
map[column.fullName] = ids.length === 1 ? ids[0] : ids;
} else if (columnRelation && columnRelation.inverseRelation.foreignKey.columns.length) {
const ids = columnRelation.inverseRelation.foreignKey.columns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
} else if (columnRelation && columnRelation.inverseRelation.joinColumns.length) {
const ids = columnRelation.inverseRelation.joinColumns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
map[column.fullName] = ids.length === 1 ? ids[0] : ids;
} else {
@ -678,12 +678,12 @@ export class EntityMetadata {
// if entity id is a relation, then extract referenced column from that relation
const columnRelation = this.relations.find(relation => relation.propertyName === column.propertyName);
if (columnRelation && columnRelation.foreignKey.columns.length) {
const ids = columnRelation.foreignKey.columns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
if (columnRelation && columnRelation.joinColumns.length) {
const ids = columnRelation.joinColumns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
map[column.fullName] = ids.length === 1 ? ids[0] : ids;
} else if (columnRelation && columnRelation.inverseRelation.foreignKey.columns.length) {
const ids = columnRelation.inverseRelation.foreignKey.columns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
} else if (columnRelation && columnRelation.inverseRelation.joinColumns.length) {
const ids = columnRelation.inverseRelation.joinColumns.map(joinColumn => entityValue[joinColumn.referencedColumn.propertyName]);
map[column.fullName] = ids.length === 1 ? ids[0] : ids;
} else {

View File

@ -4,6 +4,7 @@ import {OnDeleteType, ForeignKeyMetadata} from "./ForeignKeyMetadata";
import {JoinTableMetadata} from "./JoinTableMetadata";
import {RelationMetadataArgs} from "../metadata-args/RelationMetadataArgs";
import {ObjectLiteral} from "../common/ObjectLiteral";
import {ColumnMetadata} from "./ColumnMetadata";
/**
* Function that returns a type of the field. Returned value must be a class used on the relation.
@ -46,7 +47,7 @@ export class RelationMetadata {
*/
joinTable: JoinTableMetadata;
foreignKey: ForeignKeyMetadata;
foreignKeys: ForeignKeyMetadata[] = [];
// ---------------------------------------------------------------------
// Readonly Properties
@ -195,21 +196,52 @@ export class RelationMetadata {
if (this.isOwning) {
if (this.joinTable) {
return this.joinTable.joinColumns[0].name;
} else if (this.foreignKey && this.foreignKey.columns) {
return this.foreignKey.columns[0].name;
} else if (this.foreignKeys[0] && this.foreignKeys[0].columns) {
return this.foreignKeys[0].columns[0].name;
}
} else if (this.hasInverseSide) {
if (this.inverseRelation.joinTable) {
return this.inverseRelation.joinTable.inverseJoinColumns[0].name;
} else if (this.inverseRelation.foreignKey && this.inverseRelation.foreignKey.columns && this.inverseRelation.foreignKey.columns[0].referencedColumn) {
return this.inverseRelation.foreignKey.columns[0].referencedColumn.fullName; // todo: [0] is temporary!!
} else if (this.inverseRelation.foreignKeys[0] && this.inverseRelation.foreignKeys[0].columns && this.inverseRelation.foreignKeys[0].columns[0].referencedColumn) {
return this.inverseRelation.foreignKeys[0].columns[0].referencedColumn.fullName; // todo: [0] is temporary!!
}
}
throw new Error(`Relation name cannot be retrieved.`);
}
/**
* Join table name.
*/
get joinTableName(): string {
return this.junctionEntityMetadata.table.name;
}
/**
* Join table columns.
*/
get joinColumns(): ColumnMetadata[] {
if (!this.isOwning)
throw new Error(`Inverse join columns are only supported from owning side`);
return this.foreignKeys[0].columns;
}
/**
* Join table columns.
*/
get inverseJoinColumns(): ColumnMetadata[] {
if (!this.isOwning)
throw new Error(`Inverse join columns are only supported from owning side`);
if (!this.isManyToMany)
throw new Error(`Inverse join columns are not supported by non-many-to-many relations`);
return this.foreignKeys[1].columns;
}
/**
* Gets the name of column to which this relation is referenced.
* //Cannot be used with many-to-many relations since all referenced are in the junction table.
@ -278,7 +310,7 @@ export class RelationMetadata {
get isOwning() {
return !!(this.isManyToOne ||
(this.isManyToMany && this.joinTable) ||
(this.isOneToOne && this.foreignKey));
(this.isOneToOne && this.foreignKeys.length > 0));
}
/**

View File

@ -349,7 +349,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
if (subject.hasEntity) {
const persistValue = relation.getEntityValue(subject.entity);
if (persistValue === null) persistValueRelationId = null;
if (persistValue) persistValueRelationId = persistValue[relation.foreignKey.columns[0].referencedColumn.propertyName];
if (persistValue) persistValueRelationId = persistValue[relation.joinColumns[0].referencedColumn.propertyName];
if (persistValueRelationId === undefined) return; // skip undefined properties
}
@ -367,7 +367,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
// (example) here we seek a Details loaded from the database in the subjects
// (example) here relatedSubject.databaseEntity is a Details
// (example) and we need to compare details.id === post.detailsId
return relatedSubject.databaseEntity[relation.foreignKey.columns[0].referencedColumn.propertyName] === relationIdInDatabaseEntity;
return relatedSubject.databaseEntity[relation.joinColumns[0].referencedColumn.propertyName] === relationIdInDatabaseEntity;
});
// if not loaded yet then load it from the database
@ -377,7 +377,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
const databaseEntity = 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?
.where(qbAlias + "." + relation.foreignKey.columns[0].referencedColumn.propertyName + "=:id")
.where(qbAlias + "." + relation.joinColumns[0].referencedColumn.propertyName + "=:id")
.setParameter("id", relationIdInDatabaseEntity) // (example) subject.entity is a post here
.enableAutoRelationIdsLoad()
.getOne();
@ -428,7 +428,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
}
// (example) returns us referenced column (detail's id)
const relationIdInDatabaseEntity = subject.databaseEntity[relation.inverseRelation.foreignKey.columns[0].referencedColumn.propertyName];
const relationIdInDatabaseEntity = subject.databaseEntity[relation.inverseRelation.joinColumns[0].referencedColumn.propertyName];
// if database relation id does not exist then nothing to remove (but can this be possible?)
if (relationIdInDatabaseEntity === null || relationIdInDatabaseEntity === undefined)
@ -594,7 +594,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
} else { // this case can only be a oneToMany relation
// todo: fix issues with joinColumn[0]
// (example) returns us referenced column (detail's id)
const relationIdInDatabaseEntity = subject.databaseEntity[relation.inverseRelation.foreignKey.columns[0].referencedColumn.propertyName];
const relationIdInDatabaseEntity = subject.databaseEntity[relation.inverseRelation.joinColumns[0].referencedColumn.propertyName];
// in this case we need inverse entities not only because of cascade removes
// because we also need inverse entities to be able to perform update of entities

View File

@ -206,7 +206,7 @@ export class SubjectOperationExecutor {
// first update relations with join columns (one-to-one owner and many-to-one relations)
const updateOptions: ObjectLiteral = {};
subject.metadata.relationsWithJoinColumns.forEach(relation => {
relation.foreignKey.columns.forEach(joinColumn => {
relation.joinColumns.forEach(joinColumn => {
const referencedColumn = joinColumn.referencedColumn;
const relatedEntity = relation.getEntityValue(subject.entity);
@ -283,7 +283,7 @@ export class SubjectOperationExecutor {
const columnRelation = subject.metadata.relations.find(relation => relation.propertyName === column.propertyName);
if (entityValue && columnRelation) { // not sure if we need handle join column from inverse side
columnRelation.foreignKey.columns.forEach(joinColumn => {
columnRelation.joinColumns.forEach(joinColumn => {
let relationIdOfEntityValue = entityValue[joinColumn.referencedColumn.propertyName];
if (!relationIdOfEntityValue) {
const entityValueInsertSubject = this.insertSubjects.find(subject => subject.entity === entityValue);
@ -327,7 +327,7 @@ export class SubjectOperationExecutor {
const oneToManyAndOneToOneNonOwnerRelations = subject.metadata.oneToManyRelations.concat(subject.metadata.oneToOneRelations.filter(relation => !relation.isOwning));
subject.metadata.extractRelationValuesFromEntity(subject.entity, oneToManyAndOneToOneNonOwnerRelations)
.forEach(([relation, subRelatedEntity, inverseEntityMetadata]) => {
relation.inverseRelation.foreignKey.columns.forEach(joinColumn => {
relation.inverseRelation.joinColumns.forEach(joinColumn => {
const referencedColumn = joinColumn.referencedColumn;
const columns = inverseEntityMetadata.parentEntityMetadata ? inverseEntityMetadata.primaryColumnsWithParentIdColumns : inverseEntityMetadata.primaryColumns;
@ -340,7 +340,7 @@ export class SubjectOperationExecutor {
const columnRelation = inverseEntityMetadata.relations.find(relation => relation.propertyName === column.propertyName);
if (entityValue && columnRelation) { // not sure if we need handle join column from inverse side
columnRelation.foreignKey.columns.forEach(columnRelationJoinColumn => {
columnRelation.joinColumns.forEach(columnRelationJoinColumn => {
let relationIdOfEntityValue = entityValue[columnRelationJoinColumn.referencedColumn.propertyName];
if (!relationIdOfEntityValue) {
const entityValueInsertSubject = this.insertSubjects.find(subject => subject.entity === entityValue);
@ -507,7 +507,7 @@ export class SubjectOperationExecutor {
collectFromEmbeddeds(entity, columnsAndValuesMap, metadata.embeddeds);
metadata.relationsWithJoinColumns.forEach(relation => {
relation.foreignKey.columns.forEach(joinColumn => {
relation.joinColumns.forEach(joinColumn => {
let relationValue: any;
const value = relation.getEntityValue(entity);
@ -653,7 +653,7 @@ export class SubjectOperationExecutor {
// 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 referencedColumn = subject.metadata.treeParentRelation.foreignKey.columns[0].referencedColumn; // todo: check if joinColumn works
const referencedColumn = subject.metadata.treeParentRelation.joinColumns[0].referencedColumn; // todo: check if joinColumn works
// todo: fix joinColumns[0] usage
let newEntityId = subject.entity[referencedColumn.propertyName];
@ -792,7 +792,7 @@ export class SubjectOperationExecutor {
}
const value = relation.getEntityValue(entity);
relation.foreignKey.columns.forEach(joinColumn => {
relation.joinColumns.forEach(joinColumn => {
valueMap!.values[joinColumn.name] = value !== null && value !== undefined ? value[joinColumn.referencedColumn.propertyName] : null; // todo: should not have a call to primaryColumn, instead join column metadata should be used
});
});
@ -877,7 +877,7 @@ export class SubjectOperationExecutor {
private async updateRelations(subject: Subject) {
const values: ObjectLiteral = {};
subject.relationUpdates.forEach(setRelation => {
setRelation.relation.foreignKey.columns.forEach(joinColumn => {
setRelation.relation.joinColumns.forEach(joinColumn => {
const value = setRelation.value ? setRelation.value[joinColumn.referencedColumn.propertyName] : null;
values[joinColumn.fullName] = value; // todo: || fromInsertedSubjects ??
});

View File

@ -1454,7 +1454,7 @@ export class QueryBuilder<Entity> {
if (relation.isManyToOne || relation.isOneToOneOwner) {
// JOIN `category` `category` ON `category`.`id` = `post`.`categoryId`
const condition = relation.foreignKey.columns.map(joinColumn => {
const condition = relation.joinColumns.map(joinColumn => {
return ea(destinationTableAlias) + "." + ec(joinColumn.referencedColumn.fullName) + "=" + ea(parentAlias) + "." + ec(joinColumn.propertyName);
}).join(" AND ");
@ -1463,7 +1463,7 @@ export class QueryBuilder<Entity> {
} else if (relation.isOneToMany || relation.isOneToOneNotOwner) {
// JOIN `post` `post` ON `post`.`categoryId` = `category`.`id`
const condition = relation.inverseRelation.foreignKey.columns.map(joinColumn => {
const condition = relation.inverseRelation.joinColumns.map(joinColumn => {
return ea(destinationTableAlias!) + "." + ec(joinColumn.propertyName) + "=" + ea(parentAlias) + "." + ec(joinColumn.referencedColumn.fullName);
}).join(" AND ");

View File

@ -32,7 +32,7 @@ export class RelationCountLoader {
// todo(dima): fix issues wit multiple primary keys and remove joinColumns[0]
const relation = relationCountAttr.relation; // "category.posts"
const inverseRelation = relation.inverseRelation; // "post.category"
const referenceColumnName = inverseRelation.foreignKey.columns[0].referencedColumn.propertyName; // post id
const referenceColumnName = inverseRelation.joinColumns[0].referencedColumn.propertyName; // post id
const inverseSideTable = relation.inverseEntityMetadata.table.target; // Post
const inverseSideTableName = relation.inverseEntityMetadata.table.name; // post
const inverseSideTableAlias = relationCountAttr.alias || inverseSideTableName; // if condition (custom query builder factory) is set then relationIdAttr.alias defined

View File

@ -55,7 +55,7 @@ export class RelationIdLoader {
const relation = relationIdAttr.relation; // "category.posts"
const inverseRelation = relation.inverseRelation; // "post.category"
const referenceColumnName = inverseRelation.foreignKey.columns[0].referencedColumn.propertyName; // post id
const referenceColumnName = inverseRelation.joinColumns[0].referencedColumn.propertyName; // post id
const inverseSideTable = relation.inverseEntityMetadata.table.target; // Post
const inverseSideTableName = relation.inverseEntityMetadata.table.name; // post
const inverseSideTableAlias = relationIdAttr.alias || inverseSideTableName; // if condition (custom query builder factory) is set then relationIdAttr.alias defined

View File

@ -171,7 +171,7 @@ export class RawSqlResultsToEntityTransformer {
} else {
let referenceColumnName: string;
if (relation.isOneToMany || relation.isOneToOneNotOwner) { // todo: fix joinColumns[0]
referenceColumnName = relation.inverseRelation.foreignKey.columns[0].referencedColumn.fullName;
referenceColumnName = relation.inverseRelation.joinColumns[0].referencedColumn.fullName;
} else {
referenceColumnName = relation.isOwning ? relation.joinTable.joinColumns[0].referencedColumn.fullName : relation.inverseRelation.joinTable.joinColumns[0].referencedColumn.fullName;
}
@ -202,7 +202,7 @@ export class RawSqlResultsToEntityTransformer {
let referenceColumnName: string;
if (relation.isOneToMany) {
referenceColumnName = relation.inverseRelation.foreignKey.columns[0].referencedColumn.fullName; // todo: fix joinColumns[0]
referenceColumnName = relation.inverseRelation.joinColumns[0].referencedColumn.fullName; // todo: fix joinColumns[0]
} else {
referenceColumnName = relation.isOwning ? relation.joinTable.joinColumns[0].referencedColumn.fullName : relation.inverseRelation.joinTable.joinColumns[0].referencedColumn.fullName;

View File

@ -63,11 +63,11 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
if (relation.isOwning) {
table = relation.entityMetadata.table.name;
values[relation.name] = relatedEntityId;
conditions[relation.foreignKey.columns[0].referencedColumn.fullName] = entityId;
conditions[relation.joinColumns[0].referencedColumn.fullName] = entityId;
} else {
table = relation.inverseEntityMetadata.table.name;
values[relation.inverseRelation.name] = relatedEntityId;
conditions[relation.inverseRelation.foreignKey.columns[0].referencedColumn.fullName] = entityId;
conditions[relation.inverseRelation.joinColumns[0].referencedColumn.fullName] = entityId;
}
@ -114,11 +114,11 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
if (relation.isOwning) {
table = relation.inverseEntityMetadata.table.name;
values[relation.inverseRelation.name] = relatedEntityId;
conditions[relation.inverseRelation.foreignKey.columns[0].referencedColumn.fullName] = entityId;
conditions[relation.inverseRelation.joinColumns[0].referencedColumn.fullName] = entityId;
} else {
table = relation.entityMetadata.table.name;
values[relation.name] = relatedEntityId;
conditions[relation.foreignKey.columns[0].referencedColumn.fullName] = entityId;
conditions[relation.joinColumns[0].referencedColumn.fullName] = entityId;
}
const queryRunnerProvider = this.queryRunnerProvider ? this.queryRunnerProvider : new QueryRunnerProvider(this.connection.driver);