mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Added a foreign key in migration utils
no issue - This makes it easy to add/remove foreign key in both mysql and sqlite
This commit is contained in:
parent
68aa016264
commit
c8af2d4a04
1 changed files with 92 additions and 0 deletions
|
@ -145,6 +145,96 @@ async function dropUnique(tableName, columns, transaction) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a foreign key exists in a table over the given columns.
|
||||
*
|
||||
* @param {Object} configuration - contains all configuration for this function
|
||||
* @param {string} configuration.fromTableName - name of the table to add the foreign key to
|
||||
* @param {string} configuration.fromColumn - column of the table to add the foreign key to
|
||||
* @param {string} configuration.toTableName - name of the table to point the foreign key to
|
||||
* @param {string} configuration.toColumn - column of the table to point the foreign key to
|
||||
* @param {Object} configuration.transaction - connection object containing knex reference
|
||||
* @param {Object} configuration.transaction.knex - knex instance
|
||||
*/
|
||||
async function hasForeign({fromTable, fromColumn, toTable, toColumn, transaction}) {
|
||||
const knex = (transaction || db.knex);
|
||||
const client = knex.client.config.client;
|
||||
|
||||
if (client === 'mysql') {
|
||||
const dbName = knex.client.config.connection.database;
|
||||
const [rawConstraints] = await knex.raw(`
|
||||
SELECT i.TABLE_NAME, k.COLUMN_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME
|
||||
FROM information_schema.TABLE_CONSTRAINTS i
|
||||
INNER JOIN information_schema.KEY_COLUMN_USAGE k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME
|
||||
WHERE i.CONSTRAINT_TYPE = 'FOREIGN KEY'
|
||||
AND i.CONSTRAINT_SCHEMA=:dbName
|
||||
AND i.TABLE_NAME = :fromTable
|
||||
AND k.COLUMN_NAME = :fromColumn
|
||||
AND k.REFERENCED_TABLE_NAME = :toTable
|
||||
AND k.REFERENCED_COLUMN_NAME = :toColumn`, {dbName, fromTable, fromColumn, toTable, toColumn});
|
||||
|
||||
return rawConstraints.length >= 1;
|
||||
} else {
|
||||
const foreignKeys = await knex.raw(`PRAGMA foreign_key_list('${fromTable}');`);
|
||||
|
||||
const hasForeignKey = foreignKeys.some(foreignKey => foreignKey.table === toTable && foreignKey.from === fromColumn && foreignKey.to === toColumn);
|
||||
|
||||
return hasForeignKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a foreign key to a table.
|
||||
*
|
||||
* @param {Object} configuration - contains all configuration for this function
|
||||
* @param {string} configuration.fromTableName - name of the table to add the foreign key to
|
||||
* @param {string} configuration.fromColumn - column of the table to add the foreign key to
|
||||
* @param {string} configuration.toTableName - name of the table to point the foreign key to
|
||||
* @param {string} configuration.toColumn - column of the table to point the foreign key to
|
||||
* @param {Object} configuration.transaction - connection object containing knex reference
|
||||
* @param {Object} configuration.transaction.knex - knex instance
|
||||
*/
|
||||
async function addForeign({fromTable, fromColumn, toTable, toColumn, cascade = false, transaction}) {
|
||||
const hasForeignKey = await hasForeign({fromTable, fromColumn, toTable, toColumn, transaction});
|
||||
|
||||
if (!hasForeignKey) {
|
||||
logging.info(`Adding foreign key for: ${fromColumn} in ${fromTable} to ${toColumn} in ${toTable}`);
|
||||
return (transaction || db.knex).schema.table(fromTable, function (table) {
|
||||
if (cascade) {
|
||||
table.foreign(fromColumn).references(`${toTable}.${toColumn}`).onDelete('CASCADE');
|
||||
} else {
|
||||
table.foreign(fromColumn).references(`${toTable}.${toColumn}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logging.warn(`Skipped adding foreign key for ${fromColumn} in ${fromTable} to ${toColumn} in ${toTable} - foreign key already exists`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops a foreign key from a table.
|
||||
*
|
||||
* @param {Object} configuration - contains all configuration for this function
|
||||
* @param {string} configuration.fromTableName - name of the table to add the foreign key to
|
||||
* @param {string} configuration.fromColumn - column of the table to add the foreign key to
|
||||
* @param {string} configuration.toTableName - name of the table to point the foreign key to
|
||||
* @param {string} configuration.toColumn - column of the table to point the foreign key to
|
||||
* @param {Object} configuration.transaction - connection object containing knex reference
|
||||
* @param {Object} configuration.transaction.knex - knex instance
|
||||
*/
|
||||
async function dropForeign({fromTable, fromColumn, toTable, toColumn, transaction}) {
|
||||
const hasForeignKey = await hasForeign({fromTable, fromColumn, toTable, toColumn, transaction});
|
||||
|
||||
if (hasForeignKey) {
|
||||
logging.info(`Dropping foreign key for: ${fromColumn} in ${fromTable} to ${toColumn} in ${toTable}`);
|
||||
return (transaction || db.knex).schema.table(fromTable, function (table) {
|
||||
table.dropForeign(fromColumn);
|
||||
});
|
||||
} else {
|
||||
logging.warn(`Skipped dropping foreign key for ${fromColumn} in ${fromTable} to ${toColumn} in ${toTable} - foreign key does not exist`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if primary key index exists in a table over the given columns.
|
||||
*
|
||||
|
@ -302,6 +392,8 @@ module.exports = {
|
|||
addUnique: addUnique,
|
||||
dropUnique: dropUnique,
|
||||
addPrimaryKey: addPrimaryKey,
|
||||
addForeign: addForeign,
|
||||
dropForeign: dropForeign,
|
||||
addColumn: addColumn,
|
||||
dropColumn: dropColumn,
|
||||
getColumns: getColumns,
|
||||
|
|
Loading…
Add table
Reference in a new issue