Fix some database schema sync

This commit is contained in:
Alexandre Bodin 2021-08-10 09:36:02 +02:00
parent 38e435c165
commit 9c74f0a84e
3 changed files with 99 additions and 99 deletions

View File

@ -15,7 +15,6 @@ const postgres = {
port: 5432,
host: 'localhost',
},
// debug: true,
};
const mysql = {

View File

@ -1,5 +1,6 @@
'use strict';
const { isUndefined } = require('lodash/fp');
const debug = require('debug')('@strapi/database');
module.exports = db => ({
@ -92,82 +93,7 @@ module.exports = db => ({
// alter table
const schemaBuilder = this.getSchemaBuilder(table, trx);
await schemaBuilder.alterTable(table.name, tableBuilder => {
// Delete indexes / fks / columns
for (const removedIndex of table.indexes.removed) {
debug(`Dropping index ${removedIndex.name}`);
dropIndex(tableBuilder, removedIndex);
}
for (const updateddIndex of table.indexes.updated) {
debug(`Dropping updated index ${updateddIndex.name}`);
dropIndex(tableBuilder, updateddIndex);
}
for (const removedForeignKey of table.foreignKeys.removed) {
debug(`Dropping foreign key ${removedForeignKey.name}`);
dropForeignKey(tableBuilder, removedForeignKey);
}
for (const updatedForeignKey of table.foreignKeys.updated) {
debug(`Dropping updated foreign key ${updatedForeignKey.name}`);
dropForeignKey(tableBuilder, updatedForeignKey);
}
for (const removedColumn of table.columns.removed) {
debug(`Dropping column ${removedColumn.name}`);
dropColumn(tableBuilder, removedColumn);
}
// Update existing columns / foreign keys / indexes
for (const updatedColumn of table.columns.updated) {
debug(`Updating column ${updatedColumn.name}`);
// TODO: cleanup diffs for columns
const { object } = updatedColumn;
/*
type -> recreate the type
args -> recreate the type
unsigned
if changed then recreate the type
if removed then check if old value was true -> recreate the type else do nothing
defaultTo
reapply the default to previous data
notNullable
if null to not null we need a default value to migrate the data
*/
createColumn(tableBuilder, object).alter();
}
for (const updatedForeignKey of table.foreignKeys.updated) {
debug(`Recreating updated foreign key ${updatedForeignKey.name}`);
createForeignKey(tableBuilder, updatedForeignKey);
}
for (const updatedIndex of table.indexes.updated) {
debug(`Recreating updated index ${updatedIndex.name}`);
createIndex(tableBuilder, updatedIndex);
}
for (const addedColumn of table.columns.added) {
debug(`Creating column ${addedColumn.name}`);
createColumn(tableBuilder, addedColumn);
}
for (const addedForeignKey of table.foreignKeys.added) {
debug(`Creating foreign keys ${addedForeignKey.name}`);
createForeignKey(tableBuilder, addedForeignKey);
}
for (const addedIndex of table.indexes.added) {
debug(`Creating index ${addedIndex.name}`);
createIndex(tableBuilder, addedIndex);
}
});
await alterTable(schemaBuilder, table);
}
});
},
@ -262,7 +188,7 @@ const createColumn = (tableBuilder, column) => {
col.unsigned();
}
if (defaultTo) {
if (!isUndefined(defaultTo)) {
// TODO: allow some raw default values
col.defaultTo(...[].concat(defaultTo));
}
@ -292,9 +218,10 @@ const dropColumn = (tableBuilder, column) => {
*/
const createTable = async (schemaBuilder, table) => {
if (await schemaBuilder.hasTable(table.name)) {
throw new Error(`Table already exists ${table.name}`);
debug(`Table ${table.name} already exists trying to alter it`);
// TODO: alter the table instead
// TODO: implement a DB sync at some point
return;
}
await schemaBuilder.createTable(table.name, tableBuilder => {
@ -306,6 +233,85 @@ const createTable = async (schemaBuilder, table) => {
});
};
const alterTable = async (schemaBuilder, table) => {
await schemaBuilder.alterTable(table.name, tableBuilder => {
// Delete indexes / fks / columns
for (const removedIndex of table.indexes.removed) {
debug(`Dropping index ${removedIndex.name}`);
dropIndex(tableBuilder, removedIndex);
}
for (const updateddIndex of table.indexes.updated) {
debug(`Dropping updated index ${updateddIndex.name}`);
dropIndex(tableBuilder, updateddIndex);
}
for (const removedForeignKey of table.foreignKeys.removed) {
debug(`Dropping foreign key ${removedForeignKey.name}`);
dropForeignKey(tableBuilder, removedForeignKey);
}
for (const updatedForeignKey of table.foreignKeys.updated) {
debug(`Dropping updated foreign key ${updatedForeignKey.name}`);
dropForeignKey(tableBuilder, updatedForeignKey);
}
for (const removedColumn of table.columns.removed) {
debug(`Dropping column ${removedColumn.name}`);
dropColumn(tableBuilder, removedColumn);
}
// Update existing columns / foreign keys / indexes
for (const updatedColumn of table.columns.updated) {
debug(`Updating column ${updatedColumn.name}`);
// TODO: cleanup diffs for columns
const { object } = updatedColumn;
/*
type -> recreate the type
args -> recreate the type
unsigned
if changed then recreate the type
if removed then check if old value was true -> recreate the type else do nothing
defaultTo
reapply the default to previous data
notNullable
if null to not null we need a default value to migrate the data
*/
createColumn(tableBuilder, object).alter();
}
for (const updatedForeignKey of table.foreignKeys.updated) {
debug(`Recreating updated foreign key ${updatedForeignKey.name}`);
createForeignKey(tableBuilder, updatedForeignKey);
}
for (const updatedIndex of table.indexes.updated) {
debug(`Recreating updated index ${updatedIndex.name}`);
createIndex(tableBuilder, updatedIndex);
}
for (const addedColumn of table.columns.added) {
debug(`Creating column ${addedColumn.name}`);
createColumn(tableBuilder, addedColumn);
}
for (const addedForeignKey of table.foreignKeys.added) {
debug(`Creating foreign keys ${addedForeignKey.name}`);
createForeignKey(tableBuilder, addedForeignKey);
}
for (const addedIndex of table.indexes.added) {
debug(`Creating index ${addedIndex.name}`);
createIndex(tableBuilder, addedIndex);
}
});
};
/**
* Drops a table from a database
* @param {Knex.SchemaBuilder} schemaBuilder

View File

@ -28,14 +28,9 @@ const createTable = meta => {
columns: [],
};
// TODO: handle indexes
// TODO: handle foreignKeys
for (const key in meta.attributes) {
const attribute = meta.attributes[key];
// TODO: if relation & has a joinColumn -> create it
if (types.isRelation(attribute.type)) {
if (attribute.morphColumn && attribute.owner) {
const { idColumn, typeColumn } = attribute.morphColumn;
@ -43,34 +38,34 @@ const createTable = meta => {
table.columns.push(
createColumn(idColumn.name, {
type: 'integer',
unsigned: true,
column: {
unsigned: true,
},
})
);
table.columns.push(
createColumn(typeColumn.name, {
type: 'string',
})
);
table.columns.push(createColumn(typeColumn.name, { type: 'string' }));
} else if (attribute.joinColumn && attribute.owner) {
// NOTE: we could pass uniquness for oneToOne to avoid creating more than one to one
const { name: columnName, referencedColumn, referencedTable } = attribute.joinColumn;
table.columns.push(
createColumn(columnName, {
type: 'integer',
const column = createColumn(columnName, {
type: 'integer',
column: {
unsigned: true,
})
);
},
});
table.columns.push(column);
table.foreignKeys.push({
// TODO: generate a name
name: `${columnName}_fk`,
name: `${table.name}_${columnName}_fk`,
columns: [columnName],
referencedTable,
referencedColumns: [referencedColumn],
onDelete: 'SET NULL', // NOTE: could allow configuration
// NOTE: could allow configuration
onDelete: 'SET NULL',
});
}
} else if (shouldCreateColumn(attribute)) {