From ea7a677e4a967d0949a333453cec78c5c147f6db Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Mon, 16 Sep 2019 17:43:48 +0100 Subject: [PATCH] Added migration to normalize all empty strings to NULL (#11132) refs https://github.com/TryGhost/Ghost/issues/10388, original PR https://github.com/TryGhost/Ghost/pull/10428 - re-introduces the migration which normalizes all empty strings in the database to `NULL` - this was previously reverted due to being too large of a migration for a minor but a major is a good time to do it --- .../versions/3.0/10-remove-empty-strings.js | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 core/server/data/migrations/versions/3.0/10-remove-empty-strings.js diff --git a/core/server/data/migrations/versions/3.0/10-remove-empty-strings.js b/core/server/data/migrations/versions/3.0/10-remove-empty-strings.js new file mode 100644 index 0000000000..eddaa2d2bc --- /dev/null +++ b/core/server/data/migrations/versions/3.0/10-remove-empty-strings.js @@ -0,0 +1,81 @@ +const Promise = require('bluebird'); +const common = require('../../../../lib/common'); +const schema = require('../../../schema'); + +/* + * [{ + * tableName: 'posts', + * columns: ['custom_excerpt', 'description', 'etc...'] + * }] + * */ +const tablesToUpdate = Object.keys(schema.tables).reduce((tablesToUpdate, tableName) => { + const table = schema.tables[tableName]; + const columns = Object.keys(table).filter((columnName) => { + const column = table[columnName]; + return column.nullable && ['string', 'text'].includes(column.type); + }); + if (!columns.length) { + return tablesToUpdate; + } + return tablesToUpdate.concat({ + tableName, + columns + }); +}, []); + +const createReplace = (connection, from, to) => (tableName, columnName) => { + return connection.schema.hasTable(tableName) + .then((tableExists) => { + if (!tableExists) { + common.logging.warn( + `Table ${tableName} does not exist` + ); + return; + } + return connection.schema.hasColumn(tableName, columnName) + .then((columnExists) => { + if (!columnExists) { + common.logging.warn( + `Table '${tableName}' does not have column '${columnName}'` + ); + return; + } + + common.logging.info( + `Updating ${tableName}, setting '${from}' in ${columnName} to '${to}'` + ); + + return connection(tableName) + .where(columnName, from) + .update(columnName, to); + }); + }); +}; + +module.exports.up = ({transacting}) => { + const replaceEmptyStringWithNull = createReplace(transacting, '', null); + + return Promise.all( + tablesToUpdate.map(({tableName, columns}) => Promise.all( + columns.map( + columnName => replaceEmptyStringWithNull(tableName, columnName) + ) + )) + ); +}; + +module.exports.down = ({connection}) => { + const replaceNullWithEmptyString = createReplace(connection, null, ''); + + return Promise.all( + tablesToUpdate.map(({tableName, columns}) => Promise.all( + columns.map( + columnName => replaceNullWithEmptyString(tableName, columnName) + ) + )) + ); +}; + +module.exports.config = { + transaction: true +};