Migration: remove connection parameter from query() method

Closes #5
This commit is contained in:
Alice Gaudon 2020-11-08 15:48:34 +01:00
parent f20da06d43
commit 03d9826f93
9 changed files with 52 additions and 45 deletions

View File

@ -1,16 +1,15 @@
import Migration from "../../db/Migration"; import Migration from "../../db/Migration";
import {Connection} from "mysql";
import ModelFactory from "../../db/ModelFactory"; import ModelFactory from "../../db/ModelFactory";
import User from "../models/User"; import User from "../models/User";
import UserApprovedComponent from "../models/UserApprovedComponent"; import UserApprovedComponent from "../models/UserApprovedComponent";
export default class AddApprovedFieldToUsersTable extends Migration { export default class AddApprovedFieldToUsersTable extends Migration {
public async install(connection: Connection): Promise<void> { public async install(): Promise<void> {
await this.query('ALTER TABLE users ADD COLUMN approved BOOLEAN NOT NULL DEFAULT 0', connection); await this.query('ALTER TABLE users ADD COLUMN approved BOOLEAN NOT NULL DEFAULT 0');
} }
public async rollback(connection: Connection): Promise<void> { public async rollback(): Promise<void> {
await this.query('ALTER TABLE users DROP COLUMN approved', connection); await this.query('ALTER TABLE users DROP COLUMN approved');
} }
public registerModels(): void { public registerModels(): void {

View File

@ -1,10 +1,9 @@
import Migration from "../../db/Migration"; import Migration from "../../db/Migration";
import {Connection} from "mysql";
import ModelFactory from "../../db/ModelFactory"; import ModelFactory from "../../db/ModelFactory";
import MagicLink from "../models/MagicLink"; import MagicLink from "../models/MagicLink";
export default class CreateMagicLinksTable extends Migration { export default class CreateMagicLinksTable extends Migration {
public async install(connection: Connection): Promise<void> { public async install(): Promise<void> {
await this.query(`CREATE TABLE magic_links await this.query(`CREATE TABLE magic_links
( (
id INT NOT NULL AUTO_INCREMENT, id INT NOT NULL AUTO_INCREMENT,
@ -16,11 +15,11 @@ export default class CreateMagicLinksTable extends Migration {
generated_at DATETIME NOT NULL, generated_at DATETIME NOT NULL,
authorized BOOLEAN NOT NULL, authorized BOOLEAN NOT NULL,
PRIMARY KEY (id) PRIMARY KEY (id)
)`, connection); )`);
} }
public async rollback(connection: Connection): Promise<void> { public async rollback(): Promise<void> {
await this.query('DROP TABLE magic_links', connection); await this.query('DROP TABLE magic_links');
} }
public registerModels(): void { public registerModels(): void {

View File

@ -1,11 +1,10 @@
import Migration from "../../db/Migration"; import Migration from "../../db/Migration";
import {Connection} from "mysql";
import ModelFactory from "../../db/ModelFactory"; import ModelFactory from "../../db/ModelFactory";
import User from "../models/User"; import User from "../models/User";
import UserEmail from "../models/UserEmail"; import UserEmail from "../models/UserEmail";
export default class CreateUsersAndUserEmailsTable extends Migration { export default class CreateUsersAndUserEmailsTable extends Migration {
public async install(connection: Connection): Promise<void> { public async install(): Promise<void> {
await this.query(`CREATE TABLE users await this.query(`CREATE TABLE users
( (
id INT NOT NULL AUTO_INCREMENT, id INT NOT NULL AUTO_INCREMENT,
@ -14,7 +13,7 @@ export default class CreateUsersAndUserEmailsTable extends Migration {
created_at DATETIME NOT NULL DEFAULT NOW(), created_at DATETIME NOT NULL DEFAULT NOW(),
updated_at DATETIME NOT NULL DEFAULT NOW(), updated_at DATETIME NOT NULL DEFAULT NOW(),
PRIMARY KEY (id) PRIMARY KEY (id)
)`, connection); )`);
await this.query(`CREATE TABLE user_emails await this.query(`CREATE TABLE user_emails
( (
id INT NOT NULL AUTO_INCREMENT, id INT NOT NULL AUTO_INCREMENT,
@ -24,12 +23,12 @@ export default class CreateUsersAndUserEmailsTable extends Migration {
created_at DATETIME NOT NULL DEFAULT NOW(), created_at DATETIME NOT NULL DEFAULT NOW(),
PRIMARY KEY (id), PRIMARY KEY (id),
FOREIGN KEY user_fk (user_id) REFERENCES users (id) ON DELETE CASCADE FOREIGN KEY user_fk (user_id) REFERENCES users (id) ON DELETE CASCADE
)`, connection); )`);
} }
public async rollback(connection: Connection): Promise<void> { public async rollback(): Promise<void> {
await this.query('DROP TABLE user_emails', connection); await this.query('DROP TABLE user_emails');
await this.query('DROP TABLE users', connection); await this.query('DROP TABLE users');
} }
public registerModels(): void { public registerModels(): void {

View File

@ -1,13 +1,12 @@
import Migration from "../../db/Migration"; import Migration from "../../db/Migration";
import {Connection} from "mysql";
export default class DropNameFromUsers extends Migration { export default class DropNameFromUsers extends Migration {
public async install(connection: Connection): Promise<void> { public async install(): Promise<void> {
await this.query('ALTER TABLE users DROP COLUMN name', connection); await this.query('ALTER TABLE users DROP COLUMN name');
} }
public async rollback(connection: Connection): Promise<void> { public async rollback(): Promise<void> {
await this.query('ALTER TABLE users ADD COLUMN name VARCHAR(64)', connection); await this.query('ALTER TABLE users ADD COLUMN name VARCHAR(64)');
} }
} }

View File

@ -1,25 +1,24 @@
import Migration from "../../db/Migration"; import Migration from "../../db/Migration";
import {Connection} from "mysql";
export default class FixUserMainEmailRelation extends Migration { export default class FixUserMainEmailRelation extends Migration {
public async install(connection: Connection): Promise<void> { public async install(): Promise<void> {
await this.query(`ALTER TABLE users await this.query(`ALTER TABLE users
ADD COLUMN main_email_id INT, ADD COLUMN main_email_id INT,
ADD FOREIGN KEY main_user_email_fk (main_email_id) REFERENCES user_emails (id)`, connection); ADD FOREIGN KEY main_user_email_fk (main_email_id) REFERENCES user_emails (id)`);
await this.query(`UPDATE users u LEFT JOIN user_emails ue ON u.id = ue.user_id await this.query(`UPDATE users u LEFT JOIN user_emails ue ON u.id = ue.user_id
SET u.main_email_id=ue.id SET u.main_email_id=ue.id
WHERE ue.main = true`, connection); WHERE ue.main = true`);
await this.query(`ALTER TABLE user_emails await this.query(`ALTER TABLE user_emails
DROP COLUMN main`, connection); DROP COLUMN main`);
} }
public async rollback(connection: Connection): Promise<void> { public async rollback(): Promise<void> {
await this.query(`ALTER TABLE user_emails await this.query(`ALTER TABLE user_emails
ADD COLUMN main BOOLEAN DEFAULT false`, connection); ADD COLUMN main BOOLEAN DEFAULT false`);
await this.query(`UPDATE user_emails ue LEFT JOIN users u ON ue.id = u.main_email_id await this.query(`UPDATE user_emails ue LEFT JOIN users u ON ue.id = u.main_email_id
SET ue.main = true`, connection); SET ue.main = true`);
await this.query(`ALTER TABLE users await this.query(`ALTER TABLE users
DROP FOREIGN KEY main_user_email_fk, DROP FOREIGN KEY main_user_email_fk,
DROP COLUMN main_email_id`, connection); DROP COLUMN main_email_id`);
} }
} }

View File

@ -4,6 +4,7 @@ import {Type} from "../Utils";
export default abstract class Migration { export default abstract class Migration {
public readonly version: number; public readonly version: number;
private currentConnection?: Connection;
public constructor(version: number) { public constructor(version: number) {
this.version = version; this.version = version;
@ -13,14 +14,23 @@ export default abstract class Migration {
return this.version > currentVersion; return this.version > currentVersion;
} }
public abstract async install(connection: Connection): Promise<void>; public abstract async install(): Promise<void>;
public abstract async rollback(connection: Connection): Promise<void>; public abstract async rollback(): Promise<void>;
public registerModels?(): void; public registerModels?(): void;
protected async query(queryString: string, connection: Connection): Promise<void> { protected async query(queryString: string): Promise<void> {
await MysqlConnectionManager.query(queryString, undefined, connection); await MysqlConnectionManager.query(queryString, undefined, this.getCurrentConnection());
}
protected getCurrentConnection(): Connection {
if (!this.currentConnection) throw new Error('No current connection set.');
return this.currentConnection;
}
public setCurrentConnection(connection: Connection | null): void {
this.currentConnection = connection || undefined;
} }
} }

View File

@ -197,7 +197,9 @@ export default class MysqlConnectionManager {
if (await migration.shouldRun(currentVersion)) { if (await migration.shouldRun(currentVersion)) {
log.info('Running migration ', migration.version, migration.constructor.name); log.info('Running migration ', migration.version, migration.constructor.name);
await MysqlConnectionManager.wrapTransaction<void>(async c => { await MysqlConnectionManager.wrapTransaction<void>(async c => {
await migration.install(c); migration.setCurrentConnection(c);
await migration.install();
migration.setCurrentConnection(null);
await query('INSERT INTO migrations VALUES(?, ?, NOW())', [ await query('INSERT INTO migrations VALUES(?, ?, NOW())', [
migration.version, migration.version,
migration.constructor.name, migration.constructor.name,
@ -219,7 +221,9 @@ export default class MysqlConnectionManager {
const migration = this.migrations[migrationId]; const migration = this.migrations[migrationId];
log.info('Rolling back migration ', migration.version, migration.constructor.name); log.info('Rolling back migration ', migration.version, migration.constructor.name);
await MysqlConnectionManager.wrapTransaction<void>(async c => { await MysqlConnectionManager.wrapTransaction<void>(async c => {
await migration.rollback(c); migration.setCurrentConnection(c);
await migration.rollback();
migration.setCurrentConnection(null);
await query('DELETE FROM migrations WHERE id=?', [migration.version]); await query('DELETE FROM migrations WHERE id=?', [migration.version]);
}); });
} }

View File

@ -1,5 +1,4 @@
import Migration from "../db/Migration"; import Migration from "../db/Migration";
import {Connection} from "mysql";
import {query} from "../db/MysqlConnectionManager"; import {query} from "../db/MysqlConnectionManager";
/** /**
@ -18,17 +17,17 @@ export default class CreateMigrationsTable extends Migration {
return await super.shouldRun(currentVersion); return await super.shouldRun(currentVersion);
} }
public async install(connection: Connection): Promise<void> { public async install(): Promise<void> {
await this.query(`CREATE TABLE migrations await this.query(`CREATE TABLE migrations
( (
id INT NOT NULL, id INT NOT NULL,
name VARCHAR(64) NOT NULL, name VARCHAR(64) NOT NULL,
migration_date DATE, migration_date DATE,
PRIMARY KEY (id) PRIMARY KEY (id)
)`, connection); )`);
} }
public async rollback(connection: Connection): Promise<void> { public async rollback(): Promise<void> {
await this.query('DROP TABLE migrations', connection); await this.query('DROP TABLE migrations');
} }
} }

View File

@ -1,9 +1,8 @@
import Migration from "../db/Migration"; import Migration from "../db/Migration";
import {Connection} from "mysql";
export default class DropLegacyLogsTable extends Migration { export default class DropLegacyLogsTable extends Migration {
public async install(connection: Connection): Promise<void> { public async install(): Promise<void> {
await this.query('DROP TABLE IF EXISTS logs', connection); await this.query('DROP TABLE IF EXISTS logs');
} }
public async rollback(): Promise<void> { public async rollback(): Promise<void> {