Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ export declare class MigrationInterface {
}): void;

/**
* create column in table
* @param columnName
* @param columnType
* @param tableName
Expand All @@ -513,6 +514,16 @@ export declare class MigrationInterface {
after?: string,
}): void;

/**
* add column to table
* @param tableName
* @param columnName
* @param options
*/
addColumn(tableName: string, columnName: string, options?: {
type: FieldType,
} & CreateColumnOptions): void;

createIndex(tableName: string, columns: string[], options?: {
indexName?: string,
unique?: boolean,
Expand Down Expand Up @@ -541,4 +552,6 @@ export declare class MigrationInterface {
dropForeignKey(foreign_key: string, tableName: string): void;

insertData(table: string, data: any[]): void;

raw(sql: string, values: any[]): void;
}
21 changes: 21 additions & 0 deletions src/migration.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ function _initMigration(file, queries = {}) {
queries[file].push({ sql: builder.sql, values: builder.values });
}, ...baseAttr
});

Object.defineProperty(migration, 'createColumn', {
value: function (name, type, table, options = {}) {
_assign(options, {
Expand All @@ -192,6 +193,19 @@ function _initMigration(file, queries = {}) {
}, ...baseAttr
});

Object.defineProperty(migration, 'addColumn', {
value: function (tableName, columnName, options = {}) {
_assign(options, {
operator: 'create',
target: 'column',
table: tableName,
name: columnName
});
const builder = new ManageSQLBuilder(options);
queries[file].push({ sql: builder.sql, values: builder.values });
}, ...baseAttr
});

Object.defineProperty(migration, 'createIndex', {
value: function (table, columns, options = {}) {
_assign(options, {
Expand Down Expand Up @@ -279,6 +293,12 @@ function _initMigration(file, queries = {}) {
}, ...baseAttr
});

Object.defineProperty(migration, 'raw', {
value: function (sql, values) {
queries[file].push({ sql, values });
}, ...baseAttr
});

return migration;
}

Expand Down Expand Up @@ -328,5 +348,6 @@ async function end(context) {
module.exports = {
init,
run,
_initMigration,
end
};
246 changes: 246 additions & 0 deletions tests/migration.tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
'use strict';

let expect = null;
const { _initMigration } = require('../src/migration');

describe('migration test case', () => {
before(async function () {
const chai = await import('chai');
expect = chai.expect;
});

describe('addColumn method', () => {
it('should add column to queries with basic options', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.addColumn('users', 'email', {
type: 'varchar',
length: 255
});

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.include('ALTER TABLE `users` ADD COLUMN');
expect(queries[file][0].sql).to.include('`email` VARCHAR(255)');
expect(queries[file][0].values).to.be.an('array');
});

it('should add column with all options', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.addColumn('users', 'age', {
type: 'int',
length: 11,
unsigned: true,
allowNull: false,
default: 0,
comment: 'User age',
autoIncrement: false,
primaryKey: false,
uniqIndex: false
});

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.include('ALTER TABLE `users` ADD COLUMN');
expect(queries[file][0].sql).to.include('`age` INT(11)');
expect(queries[file][0].sql).to.include('UNSIGNED');
expect(queries[file][0].sql).to.include('NOT NULL');
expect(queries[file][0].sql).to.include('DEFAULT 0');
expect(queries[file][0].sql).to.include('COMMENT \'User age\'');
});

it('should add column with nullable and default null', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.addColumn('users', 'bio', {
type: 'text',
allowNull: true,
default: null
});

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.include('ALTER TABLE `users` ADD COLUMN');
expect(queries[file][0].sql).to.include('`bio` TEXT');
expect(queries[file][0].sql).to.include('DEFAULT NULL');
});

it('should add column with timestamp default', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.addColumn('users', 'created_at', {
type: 'datetime',
default: 'timestamp'
});

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.include('ALTER TABLE `users` ADD COLUMN');
expect(queries[file][0].sql).to.include('`created_at` DATETIME');
expect(queries[file][0].sql).to.include('DEFAULT CURRENT_TIMESTAMP');
});

it('should add column with auto increment', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.addColumn('users', 'id', {
type: 'int',
autoIncrement: true,
primaryKey: true
});

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.include('ALTER TABLE `users` ADD COLUMN');
expect(queries[file][0].sql).to.include('`id` INT(11)');
expect(queries[file][0].sql).to.include('NOT NULL');
expect(queries[file][0].sql).to.include('AUTO_INCREMENT');
});

it('should add column with after clause', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.addColumn('users', 'middle_name', {
type: 'varchar',
length: 100,
after: 'first_name'
});

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.include('ALTER TABLE `users` ADD COLUMN');
expect(queries[file][0].sql).to.include('`middle_name` VARCHAR(100)');
expect(queries[file][0].sql).to.include('AFTER `first_name`');
});

it('should add multiple columns to same file', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.addColumn('users', 'email', { type: 'varchar', length: 255 });
migrationObj.addColumn('users', 'phone', { type: 'varchar', length: 20 });

expect(queries[file].length).to.be.equal(2);
expect(queries[file][0].sql).to.include('`email`');
expect(queries[file][1].sql).to.include('`phone`');
});
});

describe('raw method', () => {
it('should add raw SQL to queries', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.raw('SELECT * FROM users WHERE id = ?', [1]);

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.be.equal('SELECT * FROM users WHERE id = ?');
expect(queries[file][0].values).to.deep.equal([1]);
});

it('should add raw SQL with multiple values', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.raw('INSERT INTO users (name, email) VALUES (?, ?)', ['John', 'john@example.com']);

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.be.equal('INSERT INTO users (name, email) VALUES (?, ?)');
expect(queries[file][0].values).to.deep.equal(['John', 'john@example.com']);
});

it('should add raw SQL with empty values array', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.raw('CREATE INDEX idx_test ON users (name)', []);

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.be.equal('CREATE INDEX idx_test ON users (name)');
expect(queries[file][0].values).to.deep.equal([]);
});

it('should add multiple raw SQL statements', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.raw('UPDATE users SET status = ? WHERE id = ?', ['active', 1]);
migrationObj.raw('DELETE FROM logs WHERE created_at < ?', [new Date('2020-01-01')]);

expect(queries[file].length).to.be.equal(2);
expect(queries[file][0].sql).to.be.equal('UPDATE users SET status = ? WHERE id = ?');
expect(queries[file][0].values).to.deep.equal(['active', 1]);
expect(queries[file][1].sql).to.be.equal('DELETE FROM logs WHERE created_at < ?');
expect(queries[file][1].values[0]).to.be.instanceOf(Date);
});

it('should add raw SQL with complex values', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

const values = [1, 'test', null, true, false, 123.45];
migrationObj.raw('INSERT INTO test VALUES (?, ?, ?, ?, ?, ?)', values);

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.be.equal('INSERT INTO test VALUES (?, ?, ?, ?, ?, ?)');
expect(queries[file][0].values).to.deep.equal(values);
});

it('should add raw SQL with JSON values', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

const jsonData = { key: 'value', nested: { data: 123 } };
migrationObj.raw('UPDATE users SET metadata = ? WHERE id = ?', [JSON.stringify(jsonData), 1]);

expect(queries[file].length).to.be.equal(1);
expect(queries[file][0].sql).to.be.equal('UPDATE users SET metadata = ? WHERE id = ?');
expect(queries[file][0].values[0]).to.be.a('string');
expect(queries[file][0].values[1]).to.be.equal(1);
});

it('should add raw SQL mixed with other migration methods', () => {
const queries = {};
const file = 'test_migration.js';
queries[file] = [];
const migrationObj = _initMigration(file, queries);

migrationObj.raw('SET FOREIGN_KEY_CHECKS = 0', []);
migrationObj.addColumn('users', 'email', { type: 'varchar', length: 255 });
migrationObj.raw('SET FOREIGN_KEY_CHECKS = 1', []);

expect(queries[file].length).to.be.equal(3);
expect(queries[file][0].sql).to.be.equal('SET FOREIGN_KEY_CHECKS = 0');
expect(queries[file][1].sql).to.include('ALTER TABLE `users` ADD COLUMN');
expect(queries[file][2].sql).to.be.equal('SET FOREIGN_KEY_CHECKS = 1');
});
});
});