UNPKG

17.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var tslib_1 = require("tslib");
4var RelationMetadata_1 = require("../metadata/RelationMetadata");
5/**
6 * Loads relation ids for the given entities.
7 */
8var RelationIdLoader = /** @class */ (function () {
9 // -------------------------------------------------------------------------
10 // Constructor
11 // -------------------------------------------------------------------------
12 function RelationIdLoader(connection) {
13 this.connection = connection;
14 }
15 /**
16 * Loads relation ids of the given entity or entities.
17 */
18 RelationIdLoader.prototype.load = function (relationOrTarget, relationNameOrEntities, entitiesOrRelatedEntities, maybeRelatedEntities) {
19 return tslib_1.__awaiter(this, void 0, void 0, function () {
20 var relation, entities, relatedEntities, entityMetadata;
21 return tslib_1.__generator(this, function (_a) {
22 if (relationOrTarget instanceof RelationMetadata_1.RelationMetadata) {
23 relation = relationOrTarget;
24 entities = relationNameOrEntities instanceof Array ? relationNameOrEntities : [relationNameOrEntities];
25 relatedEntities = entitiesOrRelatedEntities instanceof Array ? entitiesOrRelatedEntities : (entitiesOrRelatedEntities ? [entitiesOrRelatedEntities] : undefined);
26 }
27 else {
28 entityMetadata = this.connection.getMetadata(relationOrTarget);
29 relation = entityMetadata.findRelationWithPropertyPath(relationNameOrEntities);
30 if (!relation)
31 throw new Error("Relation \"" + relation + "\" was not found in \"" + entityMetadata.name + "\".");
32 entities = entitiesOrRelatedEntities instanceof Array ? entitiesOrRelatedEntities : [entitiesOrRelatedEntities];
33 relatedEntities = maybeRelatedEntities instanceof Array ? maybeRelatedEntities : (maybeRelatedEntities ? [maybeRelatedEntities] : undefined);
34 }
35 // load relation ids depend of relation type
36 if (relation.isManyToMany) {
37 return [2 /*return*/, this.loadForManyToMany(relation, entities, relatedEntities)];
38 }
39 else if (relation.isManyToOne || relation.isOneToOneOwner) {
40 return [2 /*return*/, this.loadForManyToOneAndOneToOneOwner(relation, entities, relatedEntities)];
41 }
42 else { // if (relation.isOneToMany || relation.isOneToOneNotOwner) {
43 return [2 /*return*/, this.loadForOneToManyAndOneToOneNotOwner(relation, entities, relatedEntities)];
44 }
45 return [2 /*return*/];
46 });
47 });
48 };
49 /**
50 * Loads relation ids of the given entities and groups them into the object with parent and children.
51 *
52 * todo: extract this method?
53 */
54 RelationIdLoader.prototype.loadManyToManyRelationIdsAndGroup = function (relation, entitiesOrEntities, relatedEntityOrEntities) {
55 return tslib_1.__awaiter(this, void 0, void 0, function () {
56 var isMany, entities, relationIds, relatedEntities, columns, inverseColumns;
57 return tslib_1.__generator(this, function (_a) {
58 switch (_a.label) {
59 case 0:
60 isMany = relation.isManyToMany || relation.isOneToMany;
61 entities = entitiesOrEntities instanceof Array ? entitiesOrEntities : [entitiesOrEntities];
62 if (!!relatedEntityOrEntities) return [3 /*break*/, 2];
63 return [4 /*yield*/, this.connection.relationLoader.load(relation, entitiesOrEntities)];
64 case 1:
65 relatedEntityOrEntities = _a.sent();
66 if (!relatedEntityOrEntities.length)
67 return [2 /*return*/, entities.map(function (entity) { return ({ entity: entity, related: isMany ? [] : undefined }); })];
68 _a.label = 2;
69 case 2: return [4 /*yield*/, this.load(relation, entitiesOrEntities, relatedEntityOrEntities)];
70 case 3:
71 relationIds = _a.sent();
72 relatedEntities = relatedEntityOrEntities instanceof Array ? relatedEntityOrEntities : [relatedEntityOrEntities];
73 if (relation.isManyToManyOwner) {
74 columns = relation.junctionEntityMetadata.inverseColumns.map(function (column) { return column.referencedColumn; });
75 inverseColumns = relation.junctionEntityMetadata.ownerColumns.map(function (column) { return column.referencedColumn; });
76 }
77 else if (relation.isManyToManyNotOwner) {
78 columns = relation.junctionEntityMetadata.ownerColumns.map(function (column) { return column.referencedColumn; });
79 inverseColumns = relation.junctionEntityMetadata.inverseColumns.map(function (column) { return column.referencedColumn; });
80 }
81 else if (relation.isManyToOne || relation.isOneToOneOwner) {
82 columns = relation.joinColumns.map(function (column) { return column.referencedColumn; });
83 inverseColumns = relation.entityMetadata.primaryColumns;
84 }
85 else if (relation.isOneToMany || relation.isOneToOneNotOwner) {
86 columns = relation.inverseRelation.entityMetadata.primaryColumns;
87 inverseColumns = relation.inverseRelation.joinColumns.map(function (column) { return column.referencedColumn; });
88 }
89 else {
90 }
91 return [2 /*return*/, entities.map(function (entity) {
92 var group = { entity: entity, related: isMany ? [] : undefined };
93 relationIds.forEach(function (relationId) {
94 var entityMatched = inverseColumns.every(function (column) {
95 return column.getEntityValue(entity) === relationId[column.entityMetadata.name + "_" + column.propertyPath.replace(".", "_")];
96 });
97 if (entityMatched) {
98 relatedEntities.forEach(function (relatedEntity) {
99 var relatedEntityMatched = columns.every(function (column) {
100 return column.getEntityValue(relatedEntity) === relationId[column.entityMetadata.name + "_" + relation.propertyPath.replace(".", "_") + "_" + column.propertyPath.replace(".", "_")];
101 });
102 if (relatedEntityMatched) {
103 if (isMany) {
104 group.related.push(relatedEntity);
105 }
106 else {
107 group.related = relatedEntity;
108 }
109 }
110 });
111 }
112 });
113 return group;
114 })];
115 }
116 });
117 });
118 };
119 /**
120 * Loads relation ids of the given entities and maps them into the given entity property.
121
122 async loadManyToManyRelationIdsAndMap(
123 relation: RelationMetadata,
124 entityOrEntities: ObjectLiteral|ObjectLiteral[],
125 mapToEntityOrEntities: ObjectLiteral|ObjectLiteral[],
126 propertyName: string
127 ): Promise<void> {
128
129 const relationIds = await this.loadManyToManyRelationIds(relation, entityOrEntities, mapToEntityOrEntities);
130 const mapToEntities = mapToEntityOrEntities instanceof Array ? mapToEntityOrEntities : [mapToEntityOrEntities];
131 const junctionMetadata = relation.junctionEntityMetadata!;
132 const mainAlias = junctionMetadata.name;
133 const columns = relation.isOwning ? junctionMetadata.inverseColumns : junctionMetadata.ownerColumns;
134 const inverseColumns = relation.isOwning ? junctionMetadata.ownerColumns : junctionMetadata.inverseColumns;
135
136 mapToEntities.forEach(mapToEntity => {
137 mapToEntity[propertyName] = [];
138 relationIds.forEach(relationId => {
139 const match = inverseColumns.every(column => {
140 return column.referencedColumn!.getEntityValue(mapToEntity) === relationId[mainAlias + "_" + column.propertyName];
141 });
142 if (match) {
143 if (columns.length === 1) {
144 mapToEntity[propertyName].push(relationId[mainAlias + "_" + columns[0].propertyName]);
145
146 } else {
147 const value = {};
148 columns.forEach(column => {
149 column.referencedColumn!.setEntityValue(value, relationId[mainAlias + "_" + column.propertyName]);
150 });
151 mapToEntity[propertyName].push(value);
152 }
153 }
154 });
155 });
156 }*/
157 // -------------------------------------------------------------------------
158 // Protected Methods
159 // -------------------------------------------------------------------------
160 /**
161 * Loads relation ids for the many-to-many relation.
162 */
163 RelationIdLoader.prototype.loadForManyToMany = function (relation, entities, relatedEntities) {
164 var junctionMetadata = relation.junctionEntityMetadata;
165 var mainAlias = junctionMetadata.name;
166 var columns = relation.isOwning ? junctionMetadata.ownerColumns : junctionMetadata.inverseColumns;
167 var inverseColumns = relation.isOwning ? junctionMetadata.inverseColumns : junctionMetadata.ownerColumns;
168 var qb = this.connection.createQueryBuilder();
169 // select all columns from junction table
170 junctionMetadata.ownerColumns.forEach(function (column) {
171 var columnName = column.referencedColumn.entityMetadata.name + "_" + column.referencedColumn.propertyPath.replace(".", "_");
172 qb.addSelect(mainAlias + "." + column.propertyPath, columnName);
173 });
174 junctionMetadata.inverseColumns.forEach(function (column) {
175 var columnName = column.referencedColumn.entityMetadata.name + "_" + relation.propertyPath.replace(".", "_") + "_" + column.referencedColumn.propertyPath.replace(".", "_");
176 qb.addSelect(mainAlias + "." + column.propertyPath, columnName);
177 });
178 // add conditions for the given entities
179 var condition1 = "";
180 if (columns.length === 1) {
181 qb.setParameter("values1", entities.map(function (entity) { return columns[0].referencedColumn.getEntityValue(entity); }));
182 condition1 = mainAlias + "." + columns[0].propertyPath + " IN (:...values1)"; // todo: use ANY for postgres
183 }
184 else {
185 condition1 = "(" + entities.map(function (entity, entityIndex) {
186 return columns.map(function (column) {
187 var paramName = "entity1_" + entityIndex + "_" + column.propertyName;
188 qb.setParameter(paramName, column.referencedColumn.getEntityValue(entity));
189 return mainAlias + "." + column.propertyPath + " = :" + paramName;
190 }).join(" AND ");
191 }).map(function (condition) { return "(" + condition + ")"; }).join(" OR ") + ")";
192 }
193 // add conditions for the given inverse entities
194 var condition2 = "";
195 if (relatedEntities) {
196 if (inverseColumns.length === 1) {
197 qb.setParameter("values2", relatedEntities.map(function (entity) { return inverseColumns[0].referencedColumn.getEntityValue(entity); }));
198 condition2 = mainAlias + "." + inverseColumns[0].propertyPath + " IN (:...values2)"; // todo: use ANY for postgres
199 }
200 else {
201 condition2 = "(" + relatedEntities.map(function (entity, entityIndex) {
202 return inverseColumns.map(function (column) {
203 var paramName = "entity2_" + entityIndex + "_" + column.propertyName;
204 qb.setParameter(paramName, column.referencedColumn.getEntityValue(entity));
205 return mainAlias + "." + column.propertyPath + " = :" + paramName;
206 }).join(" AND ");
207 }).map(function (condition) { return "(" + condition + ")"; }).join(" OR ") + ")";
208 }
209 }
210 // execute query
211 return qb
212 .from(junctionMetadata.target, mainAlias)
213 .where(condition1 + (condition2 ? " AND " + condition2 : ""))
214 .getRawMany();
215 };
216 /**
217 * Loads relation ids for the many-to-one and one-to-one owner relations.
218 */
219 RelationIdLoader.prototype.loadForManyToOneAndOneToOneOwner = function (relation, entities, relatedEntities) {
220 var mainAlias = relation.entityMetadata.targetName;
221 // select all columns we need
222 var qb = this.connection.createQueryBuilder();
223 relation.entityMetadata.primaryColumns.forEach(function (primaryColumn) {
224 var columnName = primaryColumn.entityMetadata.name + "_" + primaryColumn.propertyPath.replace(".", "_");
225 qb.addSelect(mainAlias + "." + primaryColumn.propertyPath, columnName);
226 });
227 relation.joinColumns.forEach(function (column) {
228 var columnName = column.referencedColumn.entityMetadata.name + "_" + relation.propertyPath.replace(".", "_") + "_" + column.referencedColumn.propertyPath.replace(".", "_");
229 qb.addSelect(mainAlias + "." + column.propertyPath, columnName);
230 });
231 // add condition for entities
232 var condition = "";
233 if (relation.entityMetadata.primaryColumns.length === 1) {
234 qb.setParameter("values", entities.map(function (entity) { return relation.entityMetadata.primaryColumns[0].getEntityValue(entity); }));
235 condition = mainAlias + "." + relation.entityMetadata.primaryColumns[0].propertyPath + " IN (:...values)";
236 }
237 else {
238 condition = entities.map(function (entity, entityIndex) {
239 return relation.entityMetadata.primaryColumns.map(function (column, columnIndex) {
240 var paramName = "entity" + entityIndex + "_" + columnIndex;
241 qb.setParameter(paramName, column.getEntityValue(entity));
242 return mainAlias + "." + column.propertyPath + " = :" + paramName;
243 }).join(" AND ");
244 }).map(function (condition) { return "(" + condition + ")"; }).join(" OR ");
245 }
246 // execute query
247 return qb.from(relation.entityMetadata.target, mainAlias)
248 .where(condition)
249 .getRawMany();
250 };
251 /**
252 * Loads relation ids for the one-to-many and one-to-one not owner relations.
253 */
254 RelationIdLoader.prototype.loadForOneToManyAndOneToOneNotOwner = function (relation, entities, relatedEntities) {
255 relation = relation.inverseRelation;
256 var mainAlias = relation.entityMetadata.targetName;
257 // select all columns we need
258 var qb = this.connection.createQueryBuilder();
259 relation.entityMetadata.primaryColumns.forEach(function (primaryColumn) {
260 var columnName = primaryColumn.entityMetadata.name + "_" + relation.inverseRelation.propertyPath.replace(".", "_") + "_" + primaryColumn.propertyPath.replace(".", "_");
261 qb.addSelect(mainAlias + "." + primaryColumn.propertyPath, columnName);
262 });
263 relation.joinColumns.forEach(function (column) {
264 var columnName = column.referencedColumn.entityMetadata.name + "_" + column.referencedColumn.propertyPath.replace(".", "_");
265 qb.addSelect(mainAlias + "." + column.propertyPath, columnName);
266 });
267 // add condition for entities
268 var condition = "";
269 if (relation.joinColumns.length === 1) {
270 qb.setParameter("values", entities.map(function (entity) { return relation.joinColumns[0].referencedColumn.getEntityValue(entity); }));
271 condition = mainAlias + "." + relation.joinColumns[0].propertyPath + " IN (:...values)";
272 }
273 else {
274 condition = entities.map(function (entity, entityIndex) {
275 return relation.joinColumns.map(function (joinColumn, joinColumnIndex) {
276 var paramName = "entity" + entityIndex + "_" + joinColumnIndex;
277 qb.setParameter(paramName, joinColumn.referencedColumn.getEntityValue(entity));
278 return mainAlias + "." + joinColumn.propertyPath + " = :" + paramName;
279 }).join(" AND ");
280 }).map(function (condition) { return "(" + condition + ")"; }).join(" OR ");
281 }
282 // execute query
283 return qb.from(relation.entityMetadata.target, mainAlias)
284 .where(condition)
285 .getRawMany();
286 };
287 return RelationIdLoader;
288}());
289exports.RelationIdLoader = RelationIdLoader;
290
291//# sourceMappingURL=RelationIdLoader.js.map