From 5d122c3c626996c846a87723353f980391e33a8f Mon Sep 17 00:00:00 2001 From: Fabien O'Carroll Date: Fri, 22 Jan 2021 14:50:11 +0000 Subject: [PATCH] Updated plan_nickname column to be nullable no-issue This value is nullable from the Stripe API so we're making sure that we can store exact values locally. SQLite3 does not supports altering columns so instead we have to: 1. Create a temp table and copy the data to it 2. Delete the original table 3. Recreate the original table with the necessary modifications 4. Copy the data from the temp table 5. Drop the temp table --- ...t-null-constraint-from-plan-name-column.js | 64 +++++++++++++++++++ core/server/data/schema/schema.js | 2 +- test/unit/data/schema/integrity_spec.js | 2 +- 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 core/server/data/migrations/versions/4.0/01-remove-not-null-constraint-from-plan-name-column.js diff --git a/core/server/data/migrations/versions/4.0/01-remove-not-null-constraint-from-plan-name-column.js b/core/server/data/migrations/versions/4.0/01-remove-not-null-constraint-from-plan-name-column.js new file mode 100644 index 0000000000..3e3f31a39b --- /dev/null +++ b/core/server/data/migrations/versions/4.0/01-remove-not-null-constraint-from-plan-name-column.js @@ -0,0 +1,64 @@ +const {createNonTransactionalMigration} = require('../../utils'); +const {createTable, deleteTable} = require('../../../schema/commands'); +const logging = require('../../../../../shared/logging'); + +const tableDef = { + id: {type: 'string', maxlength: 24, nullable: false, primary: true}, + customer_id: {type: 'string', maxlength: 255, nullable: false, unique: false, references: 'members_stripe_customers.customer_id', cascadeDelete: true}, + subscription_id: {type: 'string', maxlength: 255, nullable: false, unique: true}, + plan_id: {type: 'string', maxlength: 255, nullable: false, unique: false}, + status: {type: 'string', maxlength: 50, nullable: false}, + cancel_at_period_end: {type: 'bool', nullable: false, defaultTo: false}, + cancellation_reason: {type: 'string', maxlength: 500, nullable: true}, + current_period_end: {type: 'dateTime', nullable: false}, + start_date: {type: 'dateTime', nullable: false}, + default_payment_card_last4: {type: 'string', maxlength: 4, nullable: true}, + created_at: {type: 'dateTime', nullable: false}, + created_by: {type: 'string', maxlength: 24, nullable: false}, + updated_at: {type: 'dateTime', nullable: true}, + updated_by: {type: 'string', maxlength: 24, nullable: true}, + plan_nickname: {type: 'string', maxlength: 50, nullable: true}, + plan_interval: {type: 'string', maxlength: 50, nullable: false}, + plan_amount: {type: 'integer', nullable: false}, + plan_currency: {type: 'string', maxLength: 3, nullable: false} +}; + +module.exports = createNonTransactionalMigration( + async function up(knex) { + if (knex.client.config.client === 'mysql') { + logging.info('Removing NOT_NULL constraint from members_stripe_customers_subscriptions:plan_nickname'); + await knex.schema.alterTable('members_stripe_customers_subscriptions', (table) => { + table.string('plan_nickname').nullable().alter(); + }); + } else { + // SQLite3 doesn't support altering columns, so we have to do a wee dance with a temp table. + logging.info('Creating temporary table temp_members_stripe_customers_subscriptions'); + + await createTable('temp_members_stripe_customers_subscriptions', knex, tableDef); + + logging.info('Copying data to temporary table temp_members_stripe_customers_subscriptions'); + await knex.raw(` + INSERT INTO temp_members_stripe_customers_subscriptions + SELECT * FROM members_stripe_customers_subscriptions + `); + + logging.info('Dropping table members_stripe_customers_subscriptions'); + await deleteTable('members_stripe_customers_subscriptions', knex); + + logging.info('Creating table members_stripe_customers_subscriptions'); + await createTable('members_stripe_customers_subscriptions', knex, tableDef); + + logging.info('Copying data from temporary table to members_stripe_customers_subscriptions'); + await knex.raw(` + INSERT INTO members_stripe_customers_subscriptions + SELECT * FROM temp_members_stripe_customers_subscriptions + `); + + logging.info('Dropping temporary table temp_members_stripe_customers_subscriptions'); + await deleteTable('temp_members_stripe_customers_subscriptions', knex); + } + }, + async function down() { + // noop - we can't add a not null constraint after some of the columns have been nulled + } +); diff --git a/core/server/data/schema/schema.js b/core/server/data/schema/schema.js index faf7b2526c..22ccee025a 100644 --- a/core/server/data/schema/schema.js +++ b/core/server/data/schema/schema.js @@ -432,7 +432,7 @@ module.exports = { updated_at: {type: 'dateTime', nullable: true}, updated_by: {type: 'string', maxlength: 24, nullable: true}, /* Below fields eventually should be normalised e.g. stripe_plans table, link to here on plan_id */ - plan_nickname: {type: 'string', maxlength: 50, nullable: false}, + plan_nickname: {type: 'string', maxlength: 50, nullable: true}, plan_interval: {type: 'string', maxlength: 50, nullable: false}, plan_amount: {type: 'integer', nullable: false}, plan_currency: {type: 'string', maxLength: 3, nullable: false} diff --git a/test/unit/data/schema/integrity_spec.js b/test/unit/data/schema/integrity_spec.js index 2866139ee5..30fc93d371 100644 --- a/test/unit/data/schema/integrity_spec.js +++ b/test/unit/data/schema/integrity_spec.js @@ -32,7 +32,7 @@ const defaultSettings = require('../../../../core/server/data/schema/default-set */ describe('DB version integrity', function () { // Only these variables should need updating - const currentSchemaHash = '47e9b182da4ea9c056878354cc291191'; + const currentSchemaHash = 'deabc97adf47f5c6d086eaf4e3172f1d'; const currentFixturesHash = '370d0da0ab7c45050b2ff30bce8896ba'; const currentSettingsHash = '162f9294cc427eb32bc0577006c385ce'; const currentRoutesHash = '3d180d52c663d173a6be791ef411ed01';