333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var DriverUtils_1 = require("../../driver/DriverUtils");
var RelationIdLoader = /** @class */ (function () {
    // -------------------------------------------------------------------------
    // Constructor
    // -------------------------------------------------------------------------
    function RelationIdLoader(connection, queryRunner, relationIdAttributes) {
        this.connection = connection;
        this.queryRunner = queryRunner;
        this.relationIdAttributes = relationIdAttributes;
    }
    // -------------------------------------------------------------------------
    // Public Methods
    // -------------------------------------------------------------------------
    RelationIdLoader.prototype.load = function (rawEntities) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var promises;
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                promises = this.relationIdAttributes.map(function (relationIdAttr) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
                    var results, relation_1, joinColumns_1, table, tableName, tableAlias_1, parameters_1, condition, qb_1, results, relation, joinColumns_2, inverseJoinColumns_1, junctionAlias_1, inverseSideTableName, inverseSideTableAlias_1, junctionTableName, mappedColumns, parameters_2, joinColumnConditions, inverseJoinColumnCondition_1, condition, qb_2, results;
                    var _this = this;
                    return tslib_1.__generator(this, function (_a) {
                        switch (_a.label) {
                            case 0:
                                if (!(relationIdAttr.relation.isManyToOne || relationIdAttr.relation.isOneToOneOwner)) return [3 /*break*/, 1];
                                // example: Post and Tag
                                // loadRelationIdAndMap("post.tagId", "post.tag")
                                // we expect it to load id of tag
                                if (relationIdAttr.queryBuilderFactory)
                                    throw new Error("Additional condition can not be used with ManyToOne or OneToOne owner relations.");
                                results = rawEntities.map(function (rawEntity) {
                                    var result = {};
                                    relationIdAttr.relation.joinColumns.forEach(function (joinColumn) {
                                        result[joinColumn.databaseName] = _this.connection.driver.prepareHydratedValue(rawEntity[DriverUtils_1.DriverUtils.buildColumnAlias(_this.connection.driver, relationIdAttr.parentAlias, joinColumn.databaseName)], joinColumn.referencedColumn);
                                    });
                                    relationIdAttr.relation.entityMetadata.primaryColumns.forEach(function (primaryColumn) {
                                        result[primaryColumn.databaseName] = _this.connection.driver.prepareHydratedValue(rawEntity[DriverUtils_1.DriverUtils.buildColumnAlias(_this.connection.driver, relationIdAttr.parentAlias, primaryColumn.databaseName)], primaryColumn);
                                    });
                                    return result;
                                });
                                return [2 /*return*/, {
                                        relationIdAttribute: relationIdAttr,
                                        results: results
                                    }];
                            case 1:
                                if (!(relationIdAttr.relation.isOneToMany || relationIdAttr.relation.isOneToOneNotOwner)) return [3 /*break*/, 3];
                                relation_1 = relationIdAttr.relation;
                                joinColumns_1 = relation_1.isOwning ? relation_1.joinColumns : relation_1.inverseRelation.joinColumns;
                                table = relation_1.inverseEntityMetadata.target;
                                tableName = relation_1.inverseEntityMetadata.tableName;
                                tableAlias_1 = relationIdAttr.alias || tableName;
                                parameters_1 = {};
                                condition = rawEntities.map(function (rawEntity, index) {
                                    return joinColumns_1.map(function (joinColumn) {
                                        var parameterName = joinColumn.databaseName + index;
                                        parameters_1[parameterName] = rawEntity[DriverUtils_1.DriverUtils.buildColumnAlias(_this.connection.driver, relationIdAttr.parentAlias, joinColumn.referencedColumn.databaseName)];
                                        return tableAlias_1 + "." + joinColumn.propertyPath + " = :" + parameterName;
                                    }).join(" AND ");
                                }).map(function (condition) { return "(" + condition + ")"; })
                                    .join(" OR ");
                                // ensure we won't perform redundant queries for joined data which was not found in selection
                                // example: if post.category was not found in db then no need to execute query for category.imageIds
                                if (!condition)
                                    return [2 /*return*/, { relationIdAttribute: relationIdAttr, results: [] }];
                                qb_1 = this.connection.createQueryBuilder(this.queryRunner);
                                joinColumns_1.forEach(function (joinColumn) {
                                    qb_1.addSelect(tableAlias_1 + "." + joinColumn.propertyPath, joinColumn.databaseName);
                                });
                                relation_1.inverseRelation.entityMetadata.primaryColumns.forEach(function (primaryColumn) {
                                    qb_1.addSelect(tableAlias_1 + "." + primaryColumn.propertyPath, primaryColumn.databaseName);
                                });
                                qb_1.from(table, tableAlias_1)
                                    .where("(" + condition + ")") // need brackets because if we have additional condition and no brackets, it looks like (a = 1) OR (a = 2) AND b = 1, that is incorrect
                                    .setParameters(parameters_1);
                                // apply condition (custom query builder factory)
                                if (relationIdAttr.queryBuilderFactory)
                                    relationIdAttr.queryBuilderFactory(qb_1);
                                return [4 /*yield*/, qb_1.getRawMany()];
                            case 2:
                                results = _a.sent();
                                results.forEach(function (result) {
                                    joinColumns_1.forEach(function (column) {
                                        result[column.databaseName] = _this.connection.driver.prepareHydratedValue(result[column.databaseName], column.referencedColumn);
                                    });
                                    relation_1.inverseRelation.entityMetadata.primaryColumns.forEach(function (column) {
                                        result[column.databaseName] = _this.connection.driver.prepareHydratedValue(result[column.databaseName], column);
                                    });
                                });
                                return [2 /*return*/, {
                                        relationIdAttribute: relationIdAttr,
                                        results: results
                                    }];
                            case 3:
                                relation = relationIdAttr.relation;
                                joinColumns_2 = relation.isOwning ? relation.joinColumns : relation.inverseRelation.inverseJoinColumns;
                                inverseJoinColumns_1 = relation.isOwning ? relation.inverseJoinColumns : relation.inverseRelation.joinColumns;
                                junctionAlias_1 = relationIdAttr.junctionAlias;
                                inverseSideTableName = relationIdAttr.joinInverseSideMetadata.tableName;
                                inverseSideTableAlias_1 = relationIdAttr.alias || inverseSideTableName;
                                junctionTableName = relation.isOwning ? relation.junctionEntityMetadata.tableName : relation.inverseRelation.junctionEntityMetadata.tableName;
                                mappedColumns = rawEntities.map(function (rawEntity) {
                                    return joinColumns_2.reduce(function (map, joinColumn) {
                                        map[joinColumn.propertyPath] = rawEntity[DriverUtils_1.DriverUtils.buildColumnAlias(_this.connection.driver, relationIdAttr.parentAlias, joinColumn.referencedColumn.databaseName)];
                                        return map;
                                    }, {});
                                });
                                // ensure we won't perform redundant queries for joined data which was not found in selection
                                // example: if post.category was not found in db then no need to execute query for category.imageIds
                                if (mappedColumns.length === 0)
                                    return [2 /*return*/, { relationIdAttribute: relationIdAttr, results: [] }];
                                parameters_2 = {};
                                joinColumnConditions = mappedColumns.map(function (mappedColumn, index) {
                                    return Object.keys(mappedColumn).map(function (key) {
                                        var parameterName = key + index;
                                        parameters_2[parameterName] = mappedColumn[key];
                                        return junctionAlias_1 + "." + key + " = :" + parameterName;
                                    }).join(" AND ");
                                });
                                inverseJoinColumnCondition_1 = inverseJoinColumns_1.map(function (joinColumn) {
                                    return junctionAlias_1 + "." + joinColumn.propertyPath + " = " + inverseSideTableAlias_1 + "." + joinColumn.referencedColumn.propertyPath;
                                }).join(" AND ");
                                condition = joinColumnConditions.map(function (condition) {
                                    return "(" + condition + " AND " + inverseJoinColumnCondition_1 + ")";
                                }).join(" OR ");
                                qb_2 = this.connection.createQueryBuilder(this.queryRunner);
                                inverseJoinColumns_1.forEach(function (joinColumn) {
                                    qb_2.addSelect(junctionAlias_1 + "." + joinColumn.propertyPath, joinColumn.databaseName)
                                        .addOrderBy(junctionAlias_1 + "." + joinColumn.propertyPath);
                                });
                                joinColumns_2.forEach(function (joinColumn) {
                                    qb_2.addSelect(junctionAlias_1 + "." + joinColumn.propertyPath, joinColumn.databaseName)
                                        .addOrderBy(junctionAlias_1 + "." + joinColumn.propertyPath);
                                });
                                qb_2.from(inverseSideTableName, inverseSideTableAlias_1)
                                    .innerJoin(junctionTableName, junctionAlias_1, condition)
                                    .setParameters(parameters_2);
                                // apply condition (custom query builder factory)
                                if (relationIdAttr.queryBuilderFactory)
                                    relationIdAttr.queryBuilderFactory(qb_2);
                                return [4 /*yield*/, qb_2.getRawMany()];
                            case 4:
                                results = _a.sent();
                                results.forEach(function (result) {
                                    tslib_1.__spread(joinColumns_2, inverseJoinColumns_1).forEach(function (column) {
                                        result[column.databaseName] = _this.connection.driver.prepareHydratedValue(result[column.databaseName], column.referencedColumn);
                                    });
                                });
                                return [2 /*return*/, {
                                        relationIdAttribute: relationIdAttr,
                                        results: results
                                    }];
                        }
                    });
                }); });
                return [2 /*return*/, Promise.all(promises)];
            });
        });
    };
    return RelationIdLoader;
}());
exports.RelationIdLoader = RelationIdLoader;
 
//# sourceMappingURL=RelationIdLoader.js.map