|
| 1 | +--- |
| 2 | +title: Migrate from 4.4.5 to 4.5.1 - Strapi Developer Docs |
| 3 | +description: Learn how you can migrate your Strapi application from 4.4.5 to 4.5.1. |
| 4 | +canonicalUrl: https://docs.strapi.io/developer-docs/latest/update-migration-guides/migration-guides/v4/migration-guide-4.4.5-to-4.5.1.html |
| 5 | +--- |
| 6 | + |
| 7 | +# v4.4.5 to v4.5.1 migration guide |
| 8 | + |
| 9 | +The Strapi v4.4.5 to v4.5.1 migration guide upgrades v4.4.5 to v4.5.1. We introduced unique indexes on relationship tables and the application will not start if there are duplicated relationships. The migration guide consists of: |
| 10 | + |
| 11 | +- Upgrading the application dependencies |
| 12 | +- Installing database migration script (optional) |
| 13 | +- Reinitializing the application |
| 14 | + |
| 15 | +<!-- TODO: explain what the migration focuses on (i.e. what breaking changes it fixes). --> |
| 16 | + |
| 17 | +## Upgrading the application dependencies to 4.5.1 |
| 18 | + |
| 19 | +:::prerequisites |
| 20 | +Stop the server before starting the upgrade. |
| 21 | +::: |
| 22 | + |
| 23 | +<!-- TODO: update version numbers below 👇 --> |
| 24 | + |
| 25 | +1. Upgrade all of the Strapi packages in `package.json` to `4.5.1`: |
| 26 | + |
| 27 | + ```json |
| 28 | + // path: package.json |
| 29 | + |
| 30 | + { |
| 31 | + // ... |
| 32 | + "dependencies": { |
| 33 | + "@strapi/strapi": "4.5.1", |
| 34 | + "@strapi/plugin-users-permissions": "4.5.1", |
| 35 | + "@strapi/plugin-i18n": "4.5.1" |
| 36 | + // ... |
| 37 | + } |
| 38 | + } |
| 39 | + ``` |
| 40 | + |
| 41 | +2. Save the edited `package.json` file. |
| 42 | + |
| 43 | +3. Run either `yarn` or `npm install` to install the new version. |
| 44 | + |
| 45 | +::: tip |
| 46 | +If the operation doesn't work, try removing your `yarn.lock` or `package-lock.json`. If that doesn't help, remove the `node_modules` folder as well and try again. |
| 47 | +::: |
| 48 | + |
| 49 | +## Installing database migration script (optional) |
| 50 | + |
| 51 | +This step is only required if you have relationship duplicates in your application. If you have them, the application will not start and you will see an error message in the terminal similar to: |
| 52 | + |
| 53 | +``` |
| 54 | +error: alter table <SOME_TABLE> add constraint <SOME_TABLE_INDEX> |
| 55 | +unique (<COLUMN_NAME>, <COLUMN_NAME>) - could not create unique index <SOME_TABLE> |
| 56 | +``` |
| 57 | + |
| 58 | +To remove the duplicated relationships easily, the following migration script file was created. It will automatically remove duplicates of any relationship in the database and will be executed only once at the next launch of Strapi. |
| 59 | + |
| 60 | +To prepare the migration: |
| 61 | + |
| 62 | +1. Make a backup of the database in case something unexpected happens. |
| 63 | +2. In the `./database/migrations` folder, create a file named `2022.11.16T00.00.00.remove_duplicated_relationships.js`. |
| 64 | +3. Copy and paste the following code into the previously created file: |
| 65 | + |
| 66 | +```jsx |
| 67 | +'use strict'; |
| 68 | + |
| 69 | +/** |
| 70 | + * Get the link tables names that need to be updated |
| 71 | + */ |
| 72 | +const getLinkTables = ({ strapi }) => { |
| 73 | + const contentTypes = strapi.db.metadata; |
| 74 | + const tablesToUpdate = {}; |
| 75 | + |
| 76 | + contentTypes.forEach(contentType => { |
| 77 | + // Get attributes |
| 78 | + const attributes = contentType.attributes; |
| 79 | + |
| 80 | + // For each relation type, add the joinTable name to tablesToUpdate |
| 81 | + Object.values(attributes).forEach(attribute => { |
| 82 | + if (attribute.type === 'relation' && attribute.joinTable) { |
| 83 | + tablesToUpdate[attribute.joinTable.name] = attribute.joinTable; |
| 84 | + } |
| 85 | + }); |
| 86 | + }); |
| 87 | + |
| 88 | + return Object.values(tablesToUpdate); |
| 89 | +}; |
| 90 | + |
| 91 | +async function up(trx) { |
| 92 | + const linkTablesToUpdate = getLinkTables({ strapi }); |
| 93 | + |
| 94 | + // Remove duplicates from link tables |
| 95 | + for (const table of linkTablesToUpdate) { |
| 96 | + const tableExists = await trx.schema.hasTable(table.name); |
| 97 | + if (!tableExists) continue; |
| 98 | + |
| 99 | + strapi.log.info(`Deleting duplicates of table ${table.name}...`); |
| 100 | + |
| 101 | + try { |
| 102 | + // Query to delete duplicates from a link table |
| 103 | + let query = ` |
| 104 | + CREATE TEMPORARY TABLE tmp as SELECT DISTINCT t2.id as id |
| 105 | + FROM ?? as t1 JOIN ?? as t2 |
| 106 | + ON t1.id < t2.id |
| 107 | + `; |
| 108 | + const pivotWhereParams = []; |
| 109 | + |
| 110 | + // For each pivot column, add a on condition to the query |
| 111 | + table.pivotColumns.forEach(column => { |
| 112 | + query += ` AND t1.?? = t2.??`; |
| 113 | + pivotWhereParams.push(column, column); |
| 114 | + }); |
| 115 | + |
| 116 | + // Create temporary table with the ids of the repeated rows |
| 117 | + await trx.raw(query, [table.name, table.name, ...pivotWhereParams]); |
| 118 | + |
| 119 | + // Delete repeated rows from the original table |
| 120 | + await trx.raw(`DELETE FROM ?? WHERE id in (SELECT * FROM tmp)`, [table.name]); |
| 121 | + } finally { |
| 122 | + // Drop temporary table |
| 123 | + await trx.raw(`DROP TABLE IF EXISTS tmp `); |
| 124 | + } |
| 125 | + } |
| 126 | +} |
| 127 | + |
| 128 | +async function down() {} |
| 129 | + |
| 130 | +module.exports = { up, down }; |
| 131 | +``` |
| 132 | + |
| 133 | +<!-- TODO: complete this part --> |
| 134 | + |
| 135 | +!!!include(developer-docs/latest/update-migration-guides/migration-guides/v4/snippets/Rebuild-and-start-snippet.md)!!! |
0 commit comments