restructure updateRelations - connect

This commit is contained in:
Pierre Noël 2022-09-22 14:38:58 +02:00
parent 3ffc748b86
commit eb8d79e0c8
2 changed files with 79 additions and 81 deletions

View File

@ -505,10 +505,6 @@ const createEntityManager = (db) => {
const { joinTable } = attribute; const { joinTable } = attribute;
const { joinColumn, inverseJoinColumn, orderColumnName, inverseOrderColumnName } = const { joinColumn, inverseJoinColumn, orderColumnName, inverseOrderColumnName } =
joinTable; joinTable;
const select = [joinColumn.name];
if (isAnyToMany(attribute)) {
select.push(orderColumnName);
}
const relsToAdd = cleanRelationData.set || cleanRelationData.connect; const relsToAdd = cleanRelationData.set || cleanRelationData.connect;
const relIdsToadd = toIds(relsToAdd); const relIdsToadd = toIds(relsToAdd);
@ -740,25 +736,39 @@ const createEntityManager = (db) => {
differenceWith(isEqual, cleanRelationData.disconnect, cleanRelationData.connect) differenceWith(isEqual, cleanRelationData.disconnect, cleanRelationData.connect)
); );
if (isEmpty(cleanRelationData.connect)) {
continue;
}
await deleteRelations({ id, attribute, joinTable, db }, { relIdsToDelete }); await deleteRelations({ id, attribute, joinTable, db }, { relIdsToDelete });
// add/move // Fetch current relations to handle ordering
let max; let currentMovingRels;
const currentMovingRels = await this.createQueryBuilder(joinTable.name) if (
.select(select) isAnyToMany(attribute) ||
.where({ (isBidirectional(attribute) && isManyToAny(attribute))
[joinColumn.name]: id, ) {
[inverseJoinColumn.name]: { $in: relIdsToaddOrMove }, currentMovingRels = await this.createQueryBuilder(joinTable.name)
}) .select(select)
.where(joinTable.on || {}) .where({
.execute(); [joinColumn.name]: id,
const currentMovingRelsMap = currentMovingRels.reduce( [inverseJoinColumn.name]: { $in: relIdsToaddOrMove },
(acc, rel) => Object.assign(acc, { [rel[inverseJoinColumn.name]]: rel }), })
{} .where(joinTable.on || {})
); .execute();
}
// prepare relations to insert
const insert = cleanRelationData.connect.map((relToAdd) => ({
[joinColumn.name]: id,
[inverseJoinColumn.name]: relToAdd.id,
...(joinTable.on || {}),
...(relToAdd.__pivot || {}),
}));
// add order value
if (isAnyToMany(attribute)) { if (isAnyToMany(attribute)) {
max = ( const orderMax = (
await this.createQueryBuilder(joinTable.name) await this.createQueryBuilder(joinTable.name)
.max(orderColumnName) .max(orderColumnName)
.where({ [joinColumn.name]: id }) .where({ [joinColumn.name]: id })
@ -766,32 +776,60 @@ const createEntityManager = (db) => {
.first() .first()
.execute() .execute()
).max; ).max;
insert.forEach((row, idx) => {
row[orderColumnName] = orderMax + idx + 1;
});
} }
const nonExistingRelsIds = difference( // add inv order value
relIdsToaddOrMove, if (isBidirectional(attribute) && isManyToAny(attribute)) {
map(inverseJoinColumn.name, currentMovingRels) const nonExistingRelsIds = difference(
); relIdsToaddOrMove,
map(inverseJoinColumn.name, currentMovingRels)
);
const maxResults = await db const maxResults = await db
.getConnection() .getConnection()
.select(inverseJoinColumn.name) .select(inverseJoinColumn.name)
.max(inverseOrderColumnName, { as: 'max' }) .max(inverseOrderColumnName, { as: 'max' })
.whereIn(inverseJoinColumn.name, nonExistingRelsIds) .whereIn(inverseJoinColumn.name, nonExistingRelsIds)
.where(joinTable.on || {}) .where(joinTable.on || {})
.groupBy(inverseJoinColumn.name) .groupBy(inverseJoinColumn.name)
.from(joinTable.name); .from(joinTable.name);
const maxMap = maxResults.reduce( const maxMap = maxResults.reduce(
(acc, res) => Object.assign(acc, { [res[inverseJoinColumn.name]]: res.max }), (acc, res) => Object.assign(acc, { [res[inverseJoinColumn.name]]: res.max }),
{} {}
); );
for (const relToAddOrMove of cleanRelationData.connect) { insert.forEach((row) => {
const currentRel = currentMovingRelsMap[relToAddOrMove.id]; row[inverseOrderColumnName] = (maxMap[row[inverseJoinColumn.name]] || 0) + 1;
if (currentRel && isAnyToMany(attribute)) { });
const currentOrderIsNull = currentRel[orderColumnName] === null; }
if (!currentOrderIsNull) {
// insert rows
const query = this.createQueryBuilder(joinTable.name)
.insert(insert)
.onConflict([
joinColumn.name,
inverseJoinColumn.name,
...Object.keys(cleanRelationData.connect[0].__pivot || {}),
]);
if (isAnyToMany(attribute)) {
query.merge([orderColumnName]);
} else {
query.ignore();
}
await query.execute();
// remove gap between orders
if (isAnyToMany(attribute)) {
currentMovingRels.sort((a, b) => b[orderColumnName] - a[orderColumnName]);
for (const currentRel of currentMovingRels) {
if (currentRel[orderColumnName] !== null) {
await this.createQueryBuilder(joinTable.name) await this.createQueryBuilder(joinTable.name)
.decrement(orderColumnName, 1) .decrement(orderColumnName, 1)
.where({ .where({
@ -800,46 +838,7 @@ const createEntityManager = (db) => {
}) })
.where(joinTable.on || {}) .where(joinTable.on || {})
.execute(); .execute();
currentMovingRels.forEach((rel) => {
if (rel[orderColumnName] > currentRel[orderColumnName]) {
rel[orderColumnName] -= 1;
}
});
} }
if (currentOrderIsNull) {
max += 1;
}
await this.createQueryBuilder(joinTable.name)
.update({
[orderColumnName]: max,
})
.where({
[joinColumn.name]: id,
[inverseJoinColumn.name]: relToAddOrMove.id,
})
.where(joinTable.on || {})
.execute();
} else if (!currentRel) {
const insert = {
[joinColumn.name]: id,
[inverseJoinColumn.name]: relToAddOrMove.id,
...(relToAddOrMove.__pivot || {}),
...(joinTable.on || {}),
};
if (isAnyToMany(attribute)) {
insert[orderColumnName] = max + 1;
}
if (isBidirectional(attribute) && isManyToAny(attribute)) {
insert[inverseOrderColumnName] = (maxMap[relToAddOrMove.id] || 0) + 1;
}
await this.createQueryBuilder(joinTable.name).insert(insert).execute();
max += 1;
} }
} }
} else { } else {
@ -909,7 +908,7 @@ const createEntityManager = (db) => {
.onConflict([ .onConflict([
joinColumn.name, joinColumn.name,
inverseJoinColumn.name, inverseJoinColumn.name,
...Object.keys(joinTable.on || {}), ...Object.keys(cleanRelationData.set[0].__pivot || {}),
]); ]);
if (isAnyToMany(attribute)) { if (isAnyToMany(attribute)) {

View File

@ -99,7 +99,6 @@ describe('i18n - Find existing relations', () => {
rq = await createAuthRequest({ strapi }); rq = await createAuthRequest({ strapi });
data.shops = await builder.sanitizedFixturesFor(shopModel.singularName, strapi); data.shops = await builder.sanitizedFixturesFor(shopModel.singularName, strapi);
console.log('data.shops', data.shops);
data.products = await builder.sanitizedFixturesFor(productModel.singularName, strapi); data.products = await builder.sanitizedFixturesFor(productModel.singularName, strapi);
}); });