Skip to content

Commit

Permalink
fix(schema): use utf8mb4 charset in mysql schema
Browse files Browse the repository at this point in the history
Charset can be also configured via new `charset` option.

Closes: #513
  • Loading branch information
B4nan committed Apr 26, 2020
1 parent 86cd027 commit 82fa93d
Show file tree
Hide file tree
Showing 16 changed files with 118 additions and 101 deletions.
1 change: 1 addition & 0 deletions docs/docs/configuration.md
Expand Up @@ -112,6 +112,7 @@ export interface ConnectionOptions {
port?: number;
user?: string;
password?: string;
charset?: string;
multipleStatements?: boolean; // for mysql driver
pool?: PoolConfig; // provided by `knex`
}
Expand Down
8 changes: 5 additions & 3 deletions lib/migrations/MigrationRunner.ts
@@ -1,5 +1,5 @@
import { AbstractSqlDriver } from '../drivers';
import { MigrationsOptions, Utils } from '../utils';
import { Configuration, MigrationsOptions, Utils } from '../utils';
import { Migration } from './Migration';
import { Transaction } from '../connections';

Expand All @@ -10,15 +10,17 @@ export class MigrationRunner {
private masterTransaction?: Transaction;

constructor(protected readonly driver: AbstractSqlDriver,
protected readonly options: MigrationsOptions) { }
protected readonly options: MigrationsOptions,
protected readonly config: Configuration) { }

async run(migration: Migration, method: 'up' | 'down'): Promise<void> {
migration.reset();
await migration[method]();
let queries = migration.getQueries();

if (this.options.disableForeignKeys) {
queries.unshift(...this.helper.getSchemaBeginning().split('\n'));
const charset = this.config.get('charset')!;
queries.unshift(...this.helper.getSchemaBeginning(charset).split('\n'));
queries.push(...this.helper.getSchemaEnd().split('\n'));
}

Expand Down
2 changes: 1 addition & 1 deletion lib/migrations/Migrator.ts
Expand Up @@ -12,7 +12,7 @@ export class Migrator {

private readonly umzug: Umzug;
private readonly options = this.config.get('migrations');
private readonly runner = new MigrationRunner(this.driver, this.options);
private readonly runner = new MigrationRunner(this.driver, this.options, this.config);
private readonly generator = new MigrationGenerator(this.driver, this.options);
private readonly storage = new MigrationStorage(this.driver, this.options);

Expand Down
4 changes: 4 additions & 0 deletions lib/platforms/MySqlPlatform.ts
Expand Up @@ -5,4 +5,8 @@ export class MySqlPlatform extends Platform {

protected readonly schemaHelper = new MySqlSchemaHelper();

getDefaultCharset(): string {
return 'utf8mb4';
}

}
4 changes: 4 additions & 0 deletions lib/platforms/Platform.ts
Expand Up @@ -90,4 +90,8 @@ export abstract class Platform {
return 'bigint';
}

getDefaultCharset(): string {
return 'utf8';
}

}
8 changes: 4 additions & 4 deletions lib/schema/MySqlSchemaHelper.ts
Expand Up @@ -34,17 +34,17 @@ export class MySqlSchemaHelper extends SchemaHelper {
'0': ['0', 'false'],
};

getSchemaBeginning(): string {
return 'set names utf8;\nset foreign_key_checks = 0;\n\n';
getSchemaBeginning(charset: string): string {
return `set names ${charset};\nset foreign_key_checks = 0;\n\n`;
}

getSchemaEnd(): string {
return 'set foreign_key_checks = 1;\n';
}

finalizeTable(table: CreateTableBuilder): void {
finalizeTable(table: CreateTableBuilder, charset: string): void {
table.engine('InnoDB');
table.charset('utf8');
table.charset(charset);
}

getTypeDefinition(prop: EntityProperty): string {
Expand Down
4 changes: 2 additions & 2 deletions lib/schema/PostgreSqlSchemaHelper.ts
Expand Up @@ -37,8 +37,8 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
'null::timestamp without time zone': ['null'],
};

getSchemaBeginning(): string {
return `set names 'utf8';\nset session_replication_role = 'replica';\n\n`;
getSchemaBeginning(charset: string): string {
return `set names '${charset}';\nset session_replication_role = 'replica';\n\n`;
}

getSchemaEnd(): string {
Expand Down
4 changes: 2 additions & 2 deletions lib/schema/SchemaGenerator.ts
Expand Up @@ -166,7 +166,7 @@ export class SchemaGenerator {
return sql;
}

let ret = this.helper.getSchemaBeginning();
let ret = this.helper.getSchemaBeginning(this.config.get('charset'));
ret += sql;
ret += this.helper.getSchemaEnd();

Expand Down Expand Up @@ -198,7 +198,7 @@ export class SchemaGenerator {

meta.indexes.forEach(index => createIndex(index, false));
meta.uniques.forEach(index => createIndex(index, true));
this.helper.finalizeTable(table);
this.helper.finalizeTable(table, this.config.get('charset'));
});
}

Expand Down
4 changes: 2 additions & 2 deletions lib/schema/SchemaHelper.ts
Expand Up @@ -7,15 +7,15 @@ import { AbstractSqlConnection, Connection } from '../connections';

export abstract class SchemaHelper {

getSchemaBeginning(): string {
getSchemaBeginning(charset: string): string {
return '';
}

getSchemaEnd(): string {
return '';
}

finalizeTable(table: TableBuilder): void {
finalizeTable(table: TableBuilder, charset: string): void {
//
}

Expand Down
2 changes: 1 addition & 1 deletion lib/schema/SqliteSchemaHelper.ts
Expand Up @@ -19,7 +19,7 @@ export class SqliteSchemaHelper extends SchemaHelper {
text: ['text'],
};

getSchemaBeginning(): string {
getSchemaBeginning(charset: string): string {
return 'pragma foreign_keys = off;\n\n';
}

Expand Down
5 changes: 5 additions & 0 deletions lib/utils/Configuration.ts
Expand Up @@ -207,6 +207,10 @@ export class Configuration<D extends IDatabaseDriver = IDatabaseDriver> {
if (this.options.entitiesDirsTs.length === 0) {
this.options.entitiesDirsTs = this.options.entitiesDirs;
}

if (!this.options.charset) {
this.options.charset = this.platform.getDefaultCharset();
}
}

private validateOptions(): void {
Expand Down Expand Up @@ -253,6 +257,7 @@ export interface ConnectionOptions {
port?: number;
user?: string;
password?: string;
charset?: string;
multipleStatements?: boolean; // for mysql driver
pool?: PoolConfig;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Migrator.test.ts
Expand Up @@ -116,7 +116,7 @@ describe('Migrator', () => {
expect(spy1).toBeCalledWith('select 1 + 1');
expect(mock.mock.calls.length).toBe(6);
expect(mock.mock.calls[0][0]).toMatch('begin');
expect(mock.mock.calls[1][0]).toMatch('set names utf8;');
expect(mock.mock.calls[1][0]).toMatch('set names utf8mb4;');
expect(mock.mock.calls[2][0]).toMatch('set foreign_key_checks = 0;');
expect(mock.mock.calls[3][0]).toMatch('select 1 + 1');
expect(mock.mock.calls[4][0]).toMatch('set foreign_key_checks = 1;');
Expand Down
2 changes: 1 addition & 1 deletion tests/SchemaHelper.test.ts
Expand Up @@ -9,7 +9,7 @@ describe('SchemaHelper', () => {

test('default schema helpers', async () => {
const helper = new SchemaHelperTest();
expect(helper.getSchemaBeginning()).toBe('');
expect(helper.getSchemaBeginning('utf8')).toBe('');
expect(helper.getSchemaEnd()).toBe('');
expect(helper.getTypeDefinition({ type: 'test' } as any)).toBe('test');
expect(helper.isSame({ reference: 'scalar', type: 'number', nullable: false, columnTypes: ['integer'], default: 42 } as any, { type: 'integer', nullable: false, defaultValue: '42' } as any).all).toBe(true);
Expand Down

0 comments on commit 82fa93d

Please sign in to comment.