178 lines
7.5 KiB
JavaScript
178 lines
7.5 KiB
JavaScript
import createDebug from 'debug';
|
|
import { identifiers } from '../../utils/identifiers/index.mjs';
|
|
|
|
const debug = createDebug('strapi::database::migration');
|
|
const renameIdentifiersLongerThanMaxLength = {
|
|
name: '5.0.0-rename-identifiers-longer-than-max-length',
|
|
async up (knex, db) {
|
|
const md = db.metadata;
|
|
const diffs = findDiffs(md);
|
|
// migrate indexes before tables so we know to target the original tableName
|
|
for (const indexDiff of diffs.indexes){
|
|
await renameIndex(knex, db, indexDiff);
|
|
}
|
|
// migrate columns before table names so we know to target the original tableName
|
|
for (const columnDiff of diffs.columns){
|
|
const { full, short } = columnDiff;
|
|
const tableName = full.tableName;
|
|
const hasTable = await knex.schema.hasTable(tableName);
|
|
if (hasTable) {
|
|
// tablebuilder methods MUST be synchronous and so you cannot use async inside it, which is why we check the column here
|
|
const hasColumn = await knex.schema.hasColumn(tableName, full.columnName);
|
|
if (hasColumn) {
|
|
await knex.schema.alterTable(tableName, async (table)=>{
|
|
debug(`renaming column ${full.columnName} to ${short.columnName}`);
|
|
table.renameColumn(full.columnName, short.columnName);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
// migrate table names
|
|
for (const tableDiff of diffs.tables){
|
|
const hasTable = await knex.schema.hasTable(tableDiff.full.tableName);
|
|
if (hasTable) {
|
|
debug(`renaming table ${tableDiff.full.tableName} to ${tableDiff.short.tableName}`);
|
|
await knex.schema.renameTable(tableDiff.full.tableName, tableDiff.short.tableName);
|
|
}
|
|
}
|
|
},
|
|
async down () {
|
|
throw new Error('not implemented');
|
|
}
|
|
};
|
|
const renameIndex = async (knex, db, diff)=>{
|
|
const client = db.config.connection.client;
|
|
const short = diff.short;
|
|
const full = diff.full;
|
|
if (full.indexName === short.indexName) {
|
|
debug(`not renaming index ${full.indexName} because name hasn't changed`);
|
|
return;
|
|
}
|
|
// fk indexes can't be easily renamed, and will be recreated by db sync
|
|
// if this misses something due to the loose string matching, it's not critical, it just means index will be rebuilt in db sync
|
|
if (short.indexName.endsWith('fk') || full.indexName.endsWith('fk')) {
|
|
return;
|
|
}
|
|
debug(`renaming index from ${full.indexName} to ${short.indexName}`);
|
|
// If schema creation has never actually run before, none of these will exist, and they will throw an error
|
|
// we have no way of running an "if exists" other than a per-dialect manual check, which we won't do
|
|
// because even if it fails for some other reason, the schema sync will recreate them anyway
|
|
// Therefore, we wrap this in a nested transaction (considering we are running this migration in a transaction)
|
|
// so that we can suppress the error
|
|
try {
|
|
await knex.transaction(async (trx)=>{
|
|
if (client === 'mysql' || client === 'mariadb') {
|
|
await knex.raw('ALTER TABLE ?? RENAME INDEX ?? TO ??', [
|
|
full.tableName,
|
|
full.indexName,
|
|
short.indexName
|
|
]).transacting(trx);
|
|
} else if (client === 'pg' || client === 'postgres') {
|
|
await knex.raw('ALTER INDEX ?? RENAME TO ??', [
|
|
full.indexName,
|
|
short.indexName
|
|
]).transacting(trx);
|
|
} else if ([
|
|
'sqlite',
|
|
'sqlite3',
|
|
'better-sqlite3'
|
|
].includes(client)) {
|
|
// SQLite doesn't support renaming, so rather than trying to drop/recreate we'll let db sync handle it
|
|
debug(`SQLite does not support index renaming, not renaming index ${full.indexName}`);
|
|
} else {
|
|
debug(`No db client name matches, not renaming index ${full.indexName}`);
|
|
}
|
|
});
|
|
} catch (err) {
|
|
debug(`error creating index: ${JSON.stringify(err)}`);
|
|
}
|
|
};
|
|
const findDiffs = (shortMap)=>{
|
|
const diffs = {
|
|
tables: [],
|
|
columns: [],
|
|
indexes: []
|
|
};
|
|
const shortArr = Array.from(shortMap.entries());
|
|
shortArr.forEach(([, shortObj], index)=>{
|
|
const fullTableName = identifiers.getUnshortenedName(shortObj.tableName);
|
|
if (!fullTableName) {
|
|
throw new Error(`Missing full table name for ${shortObj.tableName}`);
|
|
}
|
|
// find table name diffs
|
|
if (shortObj.tableName !== fullTableName) {
|
|
diffs.tables.push({
|
|
full: {
|
|
index,
|
|
key: 'tableName',
|
|
tableName: fullTableName
|
|
},
|
|
short: {
|
|
index,
|
|
key: 'tableName',
|
|
tableName: shortObj.tableName
|
|
}
|
|
});
|
|
}
|
|
// find column name diffs
|
|
// eslint-disable-next-line guard-for-in
|
|
for(const attrKey in shortObj.attributes){
|
|
if (shortObj.attributes[attrKey].type === 'relation') {
|
|
continue;
|
|
}
|
|
// TODO: add more type checks so we don't need any
|
|
const attr = shortObj.attributes[attrKey];
|
|
const shortColumnName = attr.columnName;
|
|
const longColumnName = identifiers.getUnshortenedName(shortColumnName);
|
|
if (!shortColumnName || !longColumnName) {
|
|
throw new Error(`missing column name(s) for attribute ${JSON.stringify(attr, null, 2)}`);
|
|
}
|
|
if (shortColumnName && longColumnName && shortColumnName !== longColumnName) {
|
|
diffs.columns.push({
|
|
short: {
|
|
index,
|
|
tableName: fullTableName,
|
|
key: `attributes.${attrKey}`,
|
|
columnName: shortColumnName
|
|
},
|
|
full: {
|
|
index,
|
|
tableName: fullTableName,
|
|
key: `attributes.${attrKey}`,
|
|
columnName: longColumnName
|
|
}
|
|
});
|
|
}
|
|
}
|
|
// find index name diffs
|
|
// eslint-disable-next-line guard-for-in
|
|
for(const attrKey in shortObj.indexes){
|
|
const shortIndexName = shortObj.indexes[attrKey].name;
|
|
const longIndexName = identifiers.getUnshortenedName(shortIndexName);
|
|
if (!longIndexName) {
|
|
throw new Error(`Missing full index name for ${shortIndexName}`);
|
|
}
|
|
if (shortIndexName && longIndexName && shortIndexName !== longIndexName) {
|
|
diffs.indexes.push({
|
|
short: {
|
|
index,
|
|
tableName: fullTableName,
|
|
key: `indexes.${attrKey}`,
|
|
indexName: shortIndexName
|
|
},
|
|
full: {
|
|
index,
|
|
tableName: fullTableName,
|
|
key: `indexes.${attrKey}`,
|
|
indexName: longIndexName
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
return diffs;
|
|
};
|
|
|
|
export { renameIdentifiersLongerThanMaxLength };
|
|
//# sourceMappingURL=5.0.0-01-convert-identifiers-long-than-max-length.mjs.map
|