Skip to content

Commit c035f54

Browse files
added: db:create / db:drop tasks (sequelize#540)
1 parent 88ab111 commit c035f54

File tree

7 files changed

+255
-3
lines changed

7 files changed

+255
-3
lines changed

docker-compose.yml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
version: '2'
2+
3+
services:
4+
# PostgreSQL
5+
postgres-95:
6+
image: camptocamp/postgis:9.5
7+
environment:
8+
POSTGRES_USER: postgres
9+
POSTGRES_PASSWORD: postgres
10+
POSTGRES_DB: sequelize_test
11+
ports:
12+
- "5432:5432"
13+
14+
# MySQL
15+
mysql-57:
16+
image: mysql:5.7
17+
environment:
18+
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
19+
MYSQL_DATABASE: sequelize_test
20+
MYSQL_USER: root
21+
ports:
22+
- "3306:3306"

src/commands/database.js

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { _baseOptions } from '../core/yargs';
2+
import { logMigrator } from '../core/migrator';
3+
4+
import helpers from '../helpers';
5+
import { cloneDeep, defaults } from 'lodash';
6+
import clc from 'cli-color';
7+
8+
const Sequelize = helpers.generic.getSequelize();
9+
10+
exports.builder = yargs => _baseOptions(yargs).help().argv;
11+
exports.handler = async function (args) {
12+
const command = args._[0];
13+
14+
// legacy, gulp used to do this
15+
await helpers.config.init();
16+
17+
const sequelize = getDatabaseLessSequelize();
18+
const config = helpers.config.readConfig();
19+
20+
switch (command) {
21+
case 'db:create':
22+
await sequelize.query(`CREATE DATABASE ${config.database}`, {
23+
type: sequelize.QueryTypes.RAW
24+
}).catch(e => {
25+
helpers.view.error(`Error: ${e.message}`);
26+
process.exit(1);
27+
});
28+
29+
helpers.view.log(
30+
'Database',
31+
clc.blueBright(config.database),
32+
'created.'
33+
);
34+
35+
break;
36+
case 'db:drop':
37+
await sequelize.query(`DROP DATABASE ${config.database}`, {
38+
type: sequelize.QueryTypes.RAW
39+
}).catch(e => {
40+
helpers.view.error(`Error: ${e.message}`);
41+
process.exit(1);
42+
});
43+
44+
helpers.view.log(
45+
'Database',
46+
clc.blueBright(config.database),
47+
'dropped.'
48+
);
49+
50+
break;
51+
}
52+
53+
process.exit(0);
54+
};
55+
56+
function getDatabaseLessSequelize () {
57+
let config = null;
58+
59+
try {
60+
config = helpers.config.readConfig();
61+
} catch (e) {
62+
helpers.view.error(`Error: ${e.message}`);
63+
process.exit(1);
64+
}
65+
66+
config = cloneDeep(config);
67+
config = defaults(config, { logging: logMigrator });
68+
69+
switch (config.dialect) {
70+
case 'postgres':
71+
case 'postgres-native':
72+
config.database = 'postgres';
73+
break;
74+
75+
case 'mysql':
76+
delete config.database;
77+
break;
78+
79+
case 'mssql':
80+
config.database = 'master';
81+
break;
82+
83+
default:
84+
helpers.view.error(`Dialect ${config.dialect} does not support db:create / db:drop commands`);
85+
process.exit(1);
86+
}
87+
88+
try {
89+
return new Sequelize(config);
90+
} catch (e) {
91+
helpers.view.error(`Error: ${e.message}`);
92+
process.exit(1);
93+
}
94+
}

src/core/migrator.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import _ from 'lodash';
55

66
const Sequelize = helpers.generic.getSequelize();
77

8-
function logMigrator (s) {
8+
export function logMigrator (s) {
99
if (s.indexOf('Executing') !== 0) {
1010
helpers.view.log(s);
1111
}

src/sequelize.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ import seedOne from './commands/seed_one';
2828
import migrationGenerate from './commands/migration_generate';
2929
import modelGenerate from './commands/model_generate';
3030
import seedGenerate from './commands/seed_generate';
31+
import database from './commands/database';
3132

3233
import helpers from './helpers/index';
3334

34-
3535
helpers.view.teaser();
3636

3737
const cli = yargs
@@ -44,6 +44,8 @@ const cli = yargs
4444
.command('db:seed:undo', 'Deletes data from the database', seedOne)
4545
.command('db:seed:all', 'Run every seeder', seed)
4646
.command('db:seed:undo:all', 'Deletes data from the database', seed)
47+
.command('db:create', 'Create database specified by configuration', database)
48+
.command('db:drop', 'Drop database specified by configuration', database)
4749
.command('init', 'Initializes project', init)
4850
.command('init:config', 'Initializes configuration', init)
4951
.command('init:migrations', 'Initializes migrations', init)

test/db/db-create.test.js

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const expect = require('expect.js');
2+
const Support = require(__dirname + '/../support');
3+
const helpers = require(__dirname + '/../support/helpers');
4+
const gulp = require('gulp');
5+
const _ = require('lodash');
6+
7+
const prepare = function (flag, callback, options) {
8+
options = _.assign({ config: {} }, options || {});
9+
10+
const configPath = 'config/config.json';
11+
const config = _.assign({}, helpers.getTestConfig(), options.config);
12+
const configContent = JSON.stringify(config);
13+
14+
gulp
15+
.src(Support.resolveSupportPath('tmp'))
16+
.pipe(helpers.clearDirectory())
17+
.pipe(helpers.runCli('init'))
18+
.pipe(helpers.removeFile(configPath))
19+
.pipe(helpers.overwriteFile(configContent, configPath))
20+
.pipe(helpers.runCli(flag, { pipeStdout: true }))
21+
.pipe(helpers.teardown(callback));
22+
};
23+
24+
describe(Support.getTestDialectTeaser('db:create'), () => {
25+
if (Support.dialectIsPostgres()) {
26+
it('correctly creates database', function (done) {
27+
const databaseName = `my_test_db_${_.random(10000, 99999)}`;
28+
prepare(
29+
'db:create',
30+
() => {
31+
this.sequelize.query(`SELECT 1 as exists FROM pg_database WHERE datname = '${databaseName}';`, {
32+
type: this.sequelize.QueryTypes.SELECT
33+
}).then(result => {
34+
expect(result[0].exists).to.eql(1);
35+
done();
36+
});
37+
}, {
38+
config: {
39+
database: databaseName
40+
}
41+
});
42+
});
43+
}
44+
45+
if (Support.dialectIsMySQL()) {
46+
it('correctly creates database', function (done) {
47+
const databaseName = `my_test_db_${_.random(10000, 99999)}`;
48+
prepare(
49+
'db:create',
50+
() => {
51+
this.sequelize.query(`SELECT IF('${databaseName}' IN(SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA), 1, 0) AS found;`, {
52+
type: this.sequelize.QueryTypes.SELECT
53+
}).then(result => {
54+
expect(result[0].found).to.eql(1);
55+
done();
56+
});
57+
}, {
58+
config: {
59+
database: databaseName
60+
}
61+
});
62+
});
63+
}
64+
});

test/db/db-drop.test.js

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
const expect = require('expect.js');
2+
const Support = require(__dirname + '/../support');
3+
const helpers = require(__dirname + '/../support/helpers');
4+
const gulp = require('gulp');
5+
const _ = require('lodash');
6+
7+
const prepare = function (flag, callback, options) {
8+
options = _.assign({ config: {} }, options || {});
9+
10+
const configPath = 'config/config.json';
11+
const config = _.assign({}, helpers.getTestConfig(), options.config);
12+
const configContent = JSON.stringify(config);
13+
14+
gulp
15+
.src(Support.resolveSupportPath('tmp'))
16+
.pipe(helpers.clearDirectory())
17+
.pipe(helpers.runCli('init'))
18+
.pipe(helpers.removeFile(configPath))
19+
.pipe(helpers.overwriteFile(configContent, configPath))
20+
.pipe(helpers.runCli('db:create'))
21+
.pipe(helpers.runCli(flag, { pipeStdout: true }))
22+
.pipe(helpers.teardown(callback));
23+
};
24+
25+
describe(Support.getTestDialectTeaser('db:drop'), () => {
26+
if (Support.dialectIsPostgres()) {
27+
it('correctly drops database', function (done) {
28+
const databaseName = `my_test_db_${_.random(10000, 99999)}`;
29+
prepare(
30+
'db:drop',
31+
() => {
32+
this.sequelize.query(`SELECT 1 as exists FROM pg_database WHERE datname = '${databaseName}';`, {
33+
type: this.sequelize.QueryTypes.SELECT
34+
}).then(result => {
35+
expect(result).to.be.empty;
36+
done();
37+
});
38+
}, {
39+
config: {
40+
database: databaseName
41+
}
42+
});
43+
});
44+
}
45+
46+
if (Support.dialectIsMySQL()) {
47+
it('correctly drops database', function (done) {
48+
const databaseName = `my_test_db_${_.random(10000, 99999)}`;
49+
prepare(
50+
'db:drop',
51+
() => {
52+
this.sequelize.query(`SELECT IF('${databaseName}' IN(SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA), 1, 0) AS found;`, {
53+
type: this.sequelize.QueryTypes.SELECT
54+
}).then(result => {
55+
expect(result[0].found).to.eql(0);
56+
done();
57+
});
58+
}, {
59+
config: {
60+
database: databaseName
61+
}
62+
});
63+
});
64+
}
65+
});

test/support/index.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ var Support = {
144144
},
145145

146146
dialectIsMySQL: function (strict) {
147-
var envDialect = process.env.DIALECT || 'mysql';
147+
var envDialect = this.getTestDialect();
148148

149149
if (strict === undefined) {
150150
strict = false;
@@ -157,6 +157,11 @@ var Support = {
157157
}
158158
},
159159

160+
dialectIsPostgres: function (strict) {
161+
var envDialect = this.getTestDialect();
162+
return ['postgres', 'postgres-native'].indexOf(envDialect) !== -1;
163+
},
164+
160165
getTestDialectTeaser: function (moduleName) {
161166
var dialect = this.getTestDialect();
162167

0 commit comments

Comments
 (0)