I'm building a script that apply all .sql files found in a specific folder. I want those script to be executed one by one and stop execution if one fails.
My folder tree is this (and I call my script by npm run migrate-dev
from root folder)
root/
├── db/
│ ├── migrations/
│ │ ├── 01.sql
│ │ └── 02.sql
│ ├── dbConfig.js
│ └── migrate.js
├── package.json
└── .env
The two files in /migrations can be for example
01.sql
USE gamehub;
02.sql
CREATE TABLE `user` (`id` CHAR (32) NOT NULL);
migrate.js
const sqlParams = require('./dbConfig');
const mysql = require('mysql');
const fs = require('fs');
const pool = mysql.createPool(sqlParams);
if (process.env.RUN_MODE) {
console.log(`Running in dev mode`);
}
const migrate = () => {
console.log('Running migrations');
// get files list
fs.readdir('./db/migrations', (err, files) => {
if (err) {
console.log('Error while reading files in .db/migrations');
console.log(err);
throw err;
}
// generate promises list
const promises = files.map(
(file) =>
new Promise((resolve, reject) => {
fs.readFile(`./db/migrations/${file}`, 'utf-8', (err, data) => {
if (err) {
console.log(`Error while reading script ${file}`);
reject(err);
}
pool.query(data, (err, results) => {
if (err) {
console.log('Error while querying SQL');
reject(err);
}
resolve();
});
});
})
);
console.log(promises);
promises.reduce(async (prev, promise, index) => {
await prev;
console.log(`Executing script #${index}: ${files[index]}`);
promise.then(
() => Promise.resolve(),
(err) => {
console.log(err);
return;
}
);
}, Promise.resolve());
});
};
migrate();
Problems are two:
- This code is not ended, I must end it manually with CTRL+C;
- If an error occurs the execution is not stopped.
Output in case no error occurred:
> node -r dotenv/config ./db/migrate.js
Running in dev mode
Running migrations
[ Promise { <pending> }, Promise { <pending> } ]
Executing script #0: 01_selectGameHub.sql
Executing script #1: 02_createUserTable.sql
Output in case error occurred (for example if user table already exists):
> node -r dotenv/config ./db/migrate.js
Running in dev mode
Running migrations
[ Promise { <pending> }, Promise { <pending> } ]
Executing script #0: 01_selectGameHub.sql
Executing script #1: 02_createUserTable.sql
Error while querying SQL
Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 3
at Query.Sequence._packetToError
[....]
at Pool.query ([....]\node_modules\mysql\lib\Pool.js:199:23)
at [....]\db\migrate.js:28:18
at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3) {
code: 'ER_PARSE_ERROR',
errno: 1064,
sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 3",
sqlState: '42000',
index: 0,
sql: 'CREATE TABLE `user` (\n\t`id` CHAR (32) NOT NULL,\n );\n '
}