diff --git a/packages/core/database/lib/entity-manager/relations/cloning/regular-relations.js b/packages/core/database/lib/entity-manager/relations/cloning/regular-relations.js new file mode 100644 index 0000000000..b16e51d3cb --- /dev/null +++ b/packages/core/database/lib/entity-manager/relations/cloning/regular-relations.js @@ -0,0 +1,73 @@ +'use strict'; + +const { cleanInverseOrderColumn } = require('../../regular-relations'); + +const replaceRegularRelations = async ({ id, cloneId, attribute, transaction: trx }) => { + const { joinTable } = attribute; + const { joinColumn, inverseJoinColumn } = joinTable; + + // We are effectively stealing the relation from the cloned entity + await strapi.db.entityManager + .createQueryBuilder(joinTable.name) + .update({ [joinColumn.name]: id }) + .where({ [joinColumn.name]: cloneId }) + // TODO: Exclude some relations from being replaced + // .where({ $not: { [inverseJoinColumn.name]: relationsToDeleteIds } }) + .onConflict([joinColumn.name, inverseJoinColumn.name]) + .ignore() + .transacting(trx) + .execute(); +}; + +const cloneRegularRelations = async ({ id, cloneId, attribute, transaction: trx }) => { + const { joinTable } = attribute; + const { joinColumn, inverseJoinColumn, orderColumnName, inverseOrderColumnName } = joinTable; + const connection = strapi.db.getConnection(); + + // Get the columns to select + const columns = [joinColumn.name, inverseJoinColumn.name]; + if (orderColumnName) columns.push(orderColumnName); + if (inverseOrderColumnName) columns.push(inverseOrderColumnName); + if (joinTable.on) columns.push(...Object.keys(joinTable.on)); + + const selectStatement = connection + .select( + // Override joinColumn with the new id + { [joinColumn.name]: id }, + // The rest of columns will be the same + ...columns.slice(1) + ) + .where(joinColumn.name, cloneId) + // TODO: Exclude some relations from being replaced + // .where({ $not: { [inverseJoinColumn.name]: relationsToDeleteIds } }) + .from(joinTable.name) + .toSQL(); + + // Insert the clone relations + await strapi.db.entityManager + .createQueryBuilder(joinTable.name) + .insert( + strapi.db.connection.raw( + `(${columns.join(',')}) ${selectStatement.sql}`, + selectStatement.bindings + ) + ) + .onConflict([joinColumn.name, inverseJoinColumn.name]) + .ignore() + .transacting(trx) + .execute(); + + // Clean the inverse order column + if (inverseOrderColumnName) { + await cleanInverseOrderColumn({ + id, + attribute, + trx, + }); + } +}; + +module.exports = { + replaceRegularRelations, + cloneRegularRelations, +}; diff --git a/packages/core/database/package.json b/packages/core/database/package.json index 3cbba39ed9..db5670f410 100644 --- a/packages/core/database/package.json +++ b/packages/core/database/package.json @@ -35,6 +35,7 @@ "dependencies": { "@strapi/utils": "4.11.2", "date-fns": "2.30.0", + "@strapi/utils": "4.7.1", "debug": "4.3.4", "fs-extra": "10.0.0", "knex": "2.4.0",