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,11 +736,19 @@ 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 (
isAnyToMany(attribute) ||
(isBidirectional(attribute) && isManyToAny(attribute))
) {
currentMovingRels = await this.createQueryBuilder(joinTable.name)
.select(select) .select(select)
.where({ .where({
[joinColumn.name]: id, [joinColumn.name]: id,
@ -752,13 +756,19 @@ const createEntityManager = (db) => {
}) })
.where(joinTable.on || {}) .where(joinTable.on || {})
.execute(); .execute();
const currentMovingRelsMap = currentMovingRels.reduce( }
(acc, rel) => Object.assign(acc, { [rel[inverseJoinColumn.name]]: rel }),
{}
);
// 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,8 +776,14 @@ const createEntityManager = (db) => {
.first() .first()
.execute() .execute()
).max; ).max;
insert.forEach((row, idx) => {
row[orderColumnName] = orderMax + idx + 1;
});
} }
// add inv order value
if (isBidirectional(attribute) && isManyToAny(attribute)) {
const nonExistingRelsIds = difference( const nonExistingRelsIds = difference(
relIdsToaddOrMove, relIdsToaddOrMove,
map(inverseJoinColumn.name, currentMovingRels) map(inverseJoinColumn.name, currentMovingRels)
@ -787,11 +803,33 @@ const createEntityManager = (db) => {
{} {}
); );
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);
}); });