From c4031449fb38bed27b43152e5d9e048c4588b6f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20No=C3=ABl?= Date: Wed, 7 Sep 2022 18:21:54 +0200 Subject: [PATCH] implement 2 columns + adapt attachRelations --- .../core/database/lib/entity-manager/index.js | 27 ++++++++++-- .../core/database/lib/metadata/relations.js | 41 +++++++++++++++++-- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/packages/core/database/lib/entity-manager/index.js b/packages/core/database/lib/entity-manager/index.js index 79fa8af92d..15618b2126 100644 --- a/packages/core/database/lib/entity-manager/index.js +++ b/packages/core/database/lib/entity-manager/index.js @@ -475,26 +475,45 @@ const createEntityManager = (db) => { // need to set the column on the target const { joinTable } = attribute; - const { joinColumn, inverseJoinColumn } = joinTable; + const { joinColumn, inverseJoinColumn, orderColumnName, inverseOrderColumnName } = + joinTable; if (isOneToAny(attribute) && isBidirectional(attribute)) { await this.createQueryBuilder(joinTable.name) .delete() - .where({ [inverseJoinColumn.name]: castArray(data[attributeName]) }) + .where({ [inverseJoinColumn.name]: castArray(data[attributeName]) }) // TODO: would break with connect .where(joinTable.on || {}) .execute(); } const assocs = toAssocs(data[attributeName]); - const relationsToAdd = assocs.connect || assocs; + const relationsToAdd = uniqBy('id', assocs.connect || assocs); + + const maxMap = {}; + if (inverseOrderColumnName) { + await Promise.all( + relationsToAdd.map(async (rel) => { + const { max } = await this.createQueryBuilder(joinTable.name) + .max(inverseOrderColumnName) + .where({ [inverseJoinColumn.name]: rel.id }) + .where(joinTable.on || {}) + .first() + .execute(); + + maxMap[rel.id] = max; + }) + ); + } + const insert = relationsToAdd.map((data, idx) => { return { [joinColumn.name]: id, [inverseJoinColumn.name]: data.id, ...(joinTable.on || {}), ...(data.__pivot || {}), - order: idx + 1, + [orderColumnName]: idx + 1, + ...(inverseOrderColumnName ? { [inverseOrderColumnName]: maxMap[data.id] + 1 } : {}), }; }); diff --git a/packages/core/database/lib/metadata/relations.js b/packages/core/database/lib/metadata/relations.js index 2dfcb0e5ff..b3b9896949 100644 --- a/packages/core/database/lib/metadata/relations.js +++ b/packages/core/database/lib/metadata/relations.js @@ -398,12 +398,14 @@ const createJoinTable = (metadata, { attributeName, attribute, meta }) => { const joinColumnName = _.snakeCase(`${meta.singularName}_id`); let inverseJoinColumnName = _.snakeCase(`${targetMeta.singularName}_id`); + const orderColumnName = _.snakeCase(`${meta.singularName}_order`); + // if relation is slef referencing if (joinColumnName === inverseJoinColumnName) { inverseJoinColumnName = `inv_${inverseJoinColumnName}`; } - metadata.add({ + const metadataSchema = { uid: joinTableName, tableName: joinTableName, attributes: { @@ -422,7 +424,7 @@ const createJoinTable = (metadata, { attributeName, attribute, meta }) => { unsigned: true, }, }, - order: { + [orderColumnName]: { type: 'integer', column: { unsigned: true, @@ -440,6 +442,10 @@ const createJoinTable = (metadata, { attributeName, attribute, meta }) => { name: `${joinTableName}_inv_fk`, columns: [inverseJoinColumnName], }, + { + name: `${joinTableName}_order_fk`, + columns: [orderColumnName], + }, ], foreignKeys: [ { @@ -457,7 +463,7 @@ const createJoinTable = (metadata, { attributeName, attribute, meta }) => { onDelete: 'CASCADE', }, ], - }); + }; const joinTable = { name: joinTableName, @@ -469,8 +475,35 @@ const createJoinTable = (metadata, { attributeName, attribute, meta }) => { name: inverseJoinColumnName, referencedColumn: 'id', }, + orderColumnName, }; + if (isBidirectional(attribute)) { + let inverseOrderColumnName = _.snakeCase(`${targetMeta.singularName}_order`); + + // if relation is slef referencing + if (joinColumnName === inverseJoinColumnName) { + inverseOrderColumnName = `inv_${inverseOrderColumnName}`; + } + + metadataSchema.attributes[inverseOrderColumnName] = { + type: 'integer', + column: { + unsigned: true, + defaultTo: 0, + }, + }; + + metadataSchema.indexes.push({ + name: `${joinTableName}_order_inv_fk`, + columns: [inverseOrderColumnName], + }); + + joinTable.inverseOrderColumnName = inverseOrderColumnName; + } + + metadata.add(metadataSchema); + attribute.joinTable = joinTable; if (isBidirectional(attribute)) { @@ -486,6 +519,8 @@ const createJoinTable = (metadata, { attributeName, attribute, meta }) => { name: joinTableName, joinColumn: joinTable.inverseJoinColumn, inverseJoinColumn: joinTable.joinColumn, + orderColumnName: joinTable.inverseOrderColumnName, + inverseOrderColumnName: joinTable.orderColumnName, }; } };