perf: Optimized version of EntityMetadata#compareIds() for the common… · typeorm/typeorm@a9bdb37

File tree

7 files changed

lines changed

    • query-builder/transformer

7 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -618,7 +618,7 @@ export class EntityMetadata {

618618

const secondEntityIdMap = this.getEntityIdMap(secondEntity);

619619

if (!secondEntityIdMap) return false;

620620
621-

return EntityMetadata.compareIds(firstEntityIdMap, secondEntityIdMap);

621+

return OrmUtils.compareIds(firstEntityIdMap, secondEntityIdMap);

622622

}

623623
624624

/**

@@ -739,21 +739,10 @@ export class EntityMetadata {

739739

*/

740740

static difference(firstIdMaps: ObjectLiteral[], secondIdMaps: ObjectLiteral[]): ObjectLiteral[] {

741741

return firstIdMaps.filter(firstIdMap => {

742-

return !secondIdMaps.find(secondIdMap => OrmUtils.deepCompare(firstIdMap, secondIdMap));

742+

return !secondIdMaps.find(secondIdMap => OrmUtils.compareIds(firstIdMap, secondIdMap));

743743

});

744744

}

745745
746-

/**

747-

* Compares ids of the two entities.

748-

* Returns true if they match, false otherwise.

749-

*/

750-

static compareIds(firstId: ObjectLiteral|undefined, secondId: ObjectLiteral|undefined): boolean {

751-

if (firstId === undefined || firstId === null || secondId === undefined || secondId === null)

752-

return false;

753-
754-

return OrmUtils.deepCompare(firstId, secondId);

755-

}

756-
757746

/**

758747

* Creates value map from the given values and columns.

759748

* Examples of usages are primary columns map and join columns map.

Original file line numberDiff line numberDiff line change

@@ -1,7 +1,6 @@

11

import {Subject} from "./Subject";

22

import {DateUtils} from "../util/DateUtils";

33

import {ObjectLiteral} from "../common/ObjectLiteral";

4-

import {EntityMetadata} from "../metadata/EntityMetadata";

54

import {OrmUtils} from "../util/OrmUtils";

65

import {ApplyValueTransformers} from "../util/ApplyValueTransformers";

76

@@ -173,7 +172,7 @@ export class SubjectChangedColumnsComputer {

173172

const databaseRelatedEntityRelationIdMap = relation.getEntityValue(subject.databaseEntity);

174173
175174

// if relation ids are equal then we don't need to update anything

176-

const areRelatedIdsEqual = EntityMetadata.compareIds(relatedEntityRelationIdMap, databaseRelatedEntityRelationIdMap);

175+

const areRelatedIdsEqual = OrmUtils.compareIds(relatedEntityRelationIdMap, databaseRelatedEntityRelationIdMap);

177176

if (areRelatedIdsEqual) {

178177

return;

179178

} else {

Original file line numberDiff line numberDiff line change

@@ -2,7 +2,6 @@ import {Subject} from "../Subject";

22

import {OrmUtils} from "../../util/OrmUtils";

33

import {ObjectLiteral} from "../../common/ObjectLiteral";

44

import {RelationMetadata} from "../../metadata/RelationMetadata";

5-

import {EntityMetadata} from "../../metadata/EntityMetadata";

65
76

/**

87

* Builds operations needs to be executed for many-to-many relations of the given subjects.

@@ -150,7 +149,7 @@ export class ManyToManySubjectBuilder {

150149

// try to find related entity in the database

151150

// by example: find post's category in the database post's categories

152151

const relatedEntityExistInDatabase = databaseRelatedEntityIds.find(databaseRelatedEntityRelationId => {

153-

return EntityMetadata.compareIds(databaseRelatedEntityRelationId, relatedEntityRelationIdMap);

152+

return OrmUtils.compareIds(databaseRelatedEntityRelationId, relatedEntityRelationIdMap);

154153

});

155154
156155

// if entity is found then don't do anything - it means binding in junction table already exist, we don't need to add anything

@@ -207,7 +206,7 @@ export class ManyToManySubjectBuilder {

207206

// now from all entities in the persisted entity find only those which aren't found in the db

208207

const removedJunctionEntityIds = databaseRelatedEntityIds.filter(existRelationId => {

209208

return !changedInverseEntityRelationIds.find(changedRelationId => {

210-

return EntityMetadata.compareIds(changedRelationId, existRelationId);

209+

return OrmUtils.compareIds(changedRelationId, existRelationId);

211210

});

212211

});

213212
Original file line numberDiff line numberDiff line change

@@ -117,7 +117,7 @@ export class OneToManySubjectBuilder {

117117

// check if this binding really exist in the database

118118

// by example: find our category if its already bind in the database

119119

const relationIdInDatabaseSubjectRelation = relatedEntityDatabaseRelationIds.find(relatedDatabaseEntityRelationId => {

120-

return OrmUtils.deepCompare(relationIdMap, relatedDatabaseEntityRelationId);

120+

return OrmUtils.compareIds(relationIdMap, relatedDatabaseEntityRelationId);

121121

});

122122
123123

// if relationIdMap DOES NOT exist in the subject's relation in the database it means its a new relation and we need to "bind" them

Original file line numberDiff line numberDiff line change

@@ -139,7 +139,7 @@ export class OneToOneInverseSideSubjectBuilder {

139139
140140

// check if this binding really exist in the database

141141

// by example: find our post if its already bind to category in the database and its not equal to what user tries to set

142-

const areRelatedIdEqualWithDatabase = relatedEntityDatabaseRelationId && OrmUtils.deepCompare(relationIdMap, relatedEntityDatabaseRelationId);

142+

const areRelatedIdEqualWithDatabase = relatedEntityDatabaseRelationId && OrmUtils.compareIds(relationIdMap, relatedEntityDatabaseRelationId);

143143
144144

// if they aren't equal it means its a new relation and we need to "bind" them

145145

// by example: this will tell category to insert into its post relation our post we are working with

Original file line numberDiff line numberDiff line change

@@ -213,7 +213,7 @@ export class RawSqlResultsToEntityTransformer {

213213
214214

const idMaps = rawRelationIdResult.results.map(result => {

215215

const entityPrimaryIds = this.extractEntityPrimaryIds(relation, result);

216-

if (EntityMetadata.compareIds(entityPrimaryIds, valueMap) === false)

216+

if (OrmUtils.compareIds(entityPrimaryIds, valueMap) === false)

217217

return;

218218
219219

let columns: ColumnMetadata[];

Original file line numberDiff line numberDiff line change

@@ -102,7 +102,7 @@ export class OrmUtils {

102102

*

103103

* @see http://stackoverflow.com/a/1144249

104104

*/

105-

static deepCompare(...args: any[]) {

105+

static deepCompare(...args: any[]): boolean {

106106

let i: any, l: any, leftChain: any, rightChain: any;

107107
108108

if (arguments.length < 1) {

@@ -123,6 +123,26 @@ export class OrmUtils {

123123

return true;

124124

}

125125
126+

/**

127+

* Check if two entity-id-maps are the same

128+

*/

129+

static compareIds(firstId: ObjectLiteral|undefined, secondId: ObjectLiteral|undefined): boolean {

130+

if (firstId === undefined || firstId === null || secondId === undefined || secondId === null)

131+

return false;

132+
133+

// Optimized version for the common case

134+

if (

135+

((typeof firstId.id === "string" && typeof secondId.id === "string") ||

136+

(typeof firstId.id === "number" && typeof secondId.id === "number")) &&

137+

Object.keys(firstId).length === 1 &&

138+

Object.keys(secondId).length === 1

139+

) {

140+

return firstId.id === secondId.id;

141+

}

142+
143+

return OrmUtils.deepCompare(firstId, secondId);

144+

}

145+
126146

/**

127147

* Transforms given value into boolean value.

128148

*/