ããã¯ããªã«ãããããŠæžãããã®ïŒ
Node.jsã®ããŒã¿ããŒã¹ãã€ã°ã¬ãŒã·ã§ã³ããŒã«ãšããŠUmzugãšãããã®ããããããªã®ã§ãè©ŠããŠã¿ããããªãšã
Node.jsã®ããŒã¿ããŒã¹ãã€ã°ã¬ãŒã·ã§ã³ããŒã«
Node.jsã«ãããããŒã¿ããŒã¹ãã€ã°ã¬ãŒã·ã§ã³ããŒã«ãšããŠã¯ã以äžã®2ã€ãããããã§ãã
- db-migrate
- Umzug
ä»åã¯ãUmzugã®æ¹ã䜿ã£ãŠã¿ãããšãã話ã§ããã
ãšããã§ãNode.jsã§ã®ORMã«ã¯ããŒã¿ããŒã¹ãã€ã°ã¬ãŒã·ã§ã³ããŒã«ãä»å±ããŠããå Žåãå€ãã§ãã
- Prisma
- TypeORM
- Sequelize
- MicroORM
- Knex.js
Sequelizeããã³MicroORMã®ããŒã¿ããŒã¹ãã€ã°ã¬ãŒã·ã§ã³ã¯ãUmzugãçµ±åãããã®ã®ããã§ãã
ä»åã¯ãããã£ãORMã«ä»å±ãããã®ã§ã¯ãªããåç¬ã§æ±ãããã®ãã¿ãŒã²ããã«ããŸãã
Umzug
Umzugã®GitHubãªããžããªãŒã¯ãã¡ãã
GitHub - sequelize/umzug: Framework agnostic migration tool for Node.js
çŸåšã®ããŒãžã§ã³ã¯3.3.1ã§ãã
ãUmzugãã£ãŠãªãã ããïŒãšæã£ãã®ã§ããããã€ãèªã§ãåŒè¶ããšããè»¢å± ããšããæãããã§ãã
GitHub OrganizationãèŠããšSequelize Organizationã®äžã«ããã®ã§ããããµããããžã§ã¯ãã®äœçœ®ã¥ããªãã§ããããã
ç¹åŸŽã¯ä»¥äžã®ããã§ãã
- TypeScriptã§å®è£
- ãã€ã°ã¬ãŒã·ã§ã³ã®ããã®APIã®æäŸ
- CLIã®æäŸ
- ããŒã¿ããŒã¹ã«äŸåããªã
- ãã€ã°ã¬ãŒã·ã§ã³ããã»ã¹ã®ãã°ãèšé²
- ãã€ã°ã¬ãŒã·ã§ã³çšã«è€æ°ã®ã¹ãã¬ãŒãžããµããŒã
ããã¥ã¡ã³ãã¯README.md
ã®ããã§ããã
æå°ã®ãµã³ãã«ã
Umzug / Documentation / Minimal Example
䜿ãæ¹ã
CLIã
ãã£ããã以äžã®ããã«ããŠäœ¿ãæãã¿ããã§ãã
- ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ïŒJavaScriptãSQLïŒãçšæãã
- ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ã«ã¯upãšdownã®2çš®é¡ããã
- ãã€ã°ã¬ãŒã·ã§ã³ãå®è¡ããã³ã³ããã¹ãæå®ãã
- ãã€ã°ã¬ãŒã·ã§ã³ã®çµæãä¿åããã¹ãã¬ãŒãžãæå®ãã
- ã¹ãã¬ãŒãžã«ã¯JSONãã¡ã€ã«ãã¡ã¢ãªãŒãSequelizeãMongoDBããããèªåã§äœæããããšãã§ãã
- Umzug / Documentation / Storages
ããã¥ã¡ã³ãå
ã«ã¯Sequelizeãå€ãç»å Žããã®ã§ãããå¿
ãããSequelizeãšçµã¿åãããŠäœ¿ããªããã°ãªããªãããšããããšã§ã¯
ãªãããã§ãã
ãããŸã§ã¹ãã¬ãŒãžã®äžçš®ã ãšããäœçœ®ã¥ãã§ãã
Note that although this uses Sequelize, Umzug isn't coupled to Sequelize, it's just one of the (most commonly-used) supported storages.
ãšã¯ãããSequelizeã«äŸåããªãããŒã¿ããŒã¹ã¹ãã¬ãŒãžãæšæºã§ãã£ãŠæ¬²ããã£ãæ°ã¯ããŸããâŠã
ãé¡
ä»åã¯ã以äžã®ãé¡ã§Umzugãè©ŠããŠã¿ãããšæããŸãã
- 察象ã®ããŒã¿ããŒã¹ã¯MySQLãšãã
- ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ã¯SQLã§äœæãã
- ä»åã¯downã®ãã€ã°ã¬ãŒã·ã§ã³ã¯èæ ®ããªã
- ã¹ãã¬ãŒãžã¯JSONãã¡ã€ã«ãšãã
- TypeScriptã§äœæãã
ç°å¢
ä»åã®ç°å¢ã¯ãã¡ãã
$ node --version v18.18.0 $ npm --version 9.8.1
MySQLã¯172.17.0.2ã§åäœããŠãããã®ãšããããŒã¿ããŒã¹ããŠãŒã¶ãŒã¯äœææžã¿ãšããŸãã
MySQL localhost:3306 ssl practice SQL > select version(); +-----------+ | version() | +-----------+ | 8.0.34 | +-----------+ 1 row in set (0.0006 sec)
Node.jsãããžã§ã¯ããäœæãã
ãŸãã¯ãNode.jsãããžã§ã¯ããäœæããŸãã
$ npm init -y $ npm i -D typescript $ npm i -D @types/node@v18 $ npm i -D prettier $ mkdir src
äŸåé¢ä¿ã¯ãããšã§èŒããŸãããã
scripts
ã
"scripts": { "build": "tsc --project .", "build:watch": "tsc --project . --watch", "format": "prettier --write src" },
tsconfig.json
{ "compilerOptions": { "target": "esnext", "module": "commonjs", "moduleResolution": "node", "lib": ["esnext"], "baseUrl": "./src", "outDir": "dist", "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "noImplicitOverride": true, "noImplicitReturns": true, "noPropertyAccessFromIndexSignature": true, "esModuleInterop": true }, "include": [ "src" ] }
.prettierrc.json
{ "singleQuote": true, "printWidth": 120 }
Umzugã䜿ã£ãŠã¿ã
ã€ã³ã¹ããŒã«
Umzugã®ã€ã³ã¹ããŒã«ãMySQLãžã®æ¥ç¶ã«ã¯ãmysql2ã䜿ããŸãã
$ npm i umzug $ npm i mysql2
äŸåé¢ä¿ã¯ããã®ããã«ãªããŸããã
"devDependencies": { "@types/node": "^18.18.4", "prettier": "^3.0.3", "typescript": "^5.2.2" }, "dependencies": { "mysql2": "^3.6.1", "umzug": "^3.3.1" }
ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ã¯ãmigrations
ãšãããã£ã¬ã¯ããªã«é
眮ããããšã«ããŸãã
$ mkdir migrations
Umzugã䜿ã£ãããã°ã©ã ãäœæãã
äœæãããœãŒã¹ã³ãŒãã¯ãã¡ãã
src/run-umzug.ts
import fs from 'node:fs/promises'; import mysql from 'mysql2/promise'; import { Umzug, JSONStorage, MigrationParams, Resolver } from 'umzug'; const main = async () => { const conn = await mysql.createConnection({ host: '172.17.0.2', port: 3306, user: 'kazuhira', password: 'password', database: 'practice', multipleStatements: true, // ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ïŒSQLïŒã«è€æ°ã®SQLãå«ããå Žå }); try { const resolver: Resolver<mysql.Connection> = (params: MigrationParams<mysql.Connection>) => ({ name: params.name, up: async () => { log(`target migration file => ${params.path}`); const sql = (await fs.readFile(params.path!)).toString(); return await params.context.query(sql); }, down: async () => { // downã¯ä»åã¯é€å€ }, }); const umzug = new Umzug({ migrations: { glob: 'migrations/**/*.sql', resolve: resolver }, context: conn, storage: new JSONStorage(), // ããã©ã«ãã§ã¯umzug.jsonãšãããã¡ã€ã«ã«ä¿å logger: console, }); // é©çšæžã¿ã®ãã€ã°ã¬ãŒã·ã§ã³ã衚瀺 const executedMetas = await umzug.executed(); if (executedMetas.length > 0) { log('current executed migrations'); for (const meta of executedMetas) { log(`executed, name = ${meta.name}, path = ${meta.path}`); } } // æªé©çšã®ãã€ã°ã¬ãŒã·ã§ã³ã衚瀺 const pendingMetas = await umzug.pending(); if (pendingMetas.length > 0) { log('current pending migrations'); for (const meta of pendingMetas) { log(`pending, name = ${meta.name}, path = ${meta.path}`); } } log('start Umzug migration...'); await umzug.up(); log('end Umzug migration'); } finally { await conn.end(); } }; main().catch((e) => console.error(e)); function log(message: string) { console.info(`[${new Date().toISOString()}] ${message}`); }
ä»åã¯ã以äžã®ããã«async
ãªé¢æ°ãäœæããŠåŒã³åºã圢åŒã«ããŸããã
const main = async () => { // ããã«åŠçãæžã }; main().catch((e) => console.error(e));
main
ã®äžã説æããŠãããŸãã
ããŒã¿ããŒã¹æ¥ç¶ã§ããä»åã¯MySQLãžæ¥ç¶ããã®ã§ãmysql2ã䜿çšããŸãã
const conn = await mysql.createConnection({ host: '172.17.0.2', port: 3306, user: 'kazuhira', password: 'password', database: 'practice', multipleStatements: true, // ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ïŒSQLïŒã«è€æ°ã®SQLãå«ããå Žå });
multipleStatements
ã§ãããããã©ã«ãã¯false
ã§è€æ°ã®SQLãå®è¡ã§ããŸããã
ããšã§èšèŒããŸããã以äžã®ãããªè€æ°ã®SQLæãå«ããã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãäœæããŠå®è¡ãããš
migrations/20231009-003.sql
insert into book(isbn, title, price) values('978-4798161488', 'MySQL培åºå ¥é 第4ç MySQL 8.0察å¿', 4180); insert into book(isbn, title, price) values('978-4798147406', '詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã', 3960); insert into book(isbn, title, price) values('978-4873116389', 'å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç', 5280);
以äžã®ããã«æ§æãšã©ãŒã«ãªããŸããmultipleStatements
ãtrue
ã«ããããšã§ããã®ãããªãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãå®è¡ã§ããããã«
ãªããŸãã
MigrationError: Migration 20231009-003.sql (up) failed: Original 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 'insert into book(isbn, title, price) values('978-4798147406', '詳解MySQL 5.7 Ê' at line 2
次ã¯Resolver
ã®èšå®ãæžããŠããã®ã§ããããã®åã«å
ã«Umzugèªäœã®èšå®ã説æããŸãããã
const umzug = new Umzug({ migrations: { glob: 'migrations/**/*.sql', resolve: resolver }, context: conn, storage: new JSONStorage(), // ããã©ã«ãã§ã¯umzug.jsonãšãããã¡ã€ã«ã«ä¿å logger: console, });
åããããã£ã®æå³ãšæå®ããå€ã¯ããããã以äžã§ãã
migrations
⊠ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ã®çœ®ãå Žæãglob
ããããã£ã§æå®ãã- globã®å®è£ ã«ã¯node-globãã䜿ãããŠãã
context
⊠ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ã®å®è¡æã«æž¡ããªããžã§ã¯ãstorage
⊠ãã€ã°ã¬ãŒã·ã§ã³çµæã®ä¿åå logger
⊠ãã°åºåã«äœ¿çšãããªããžã§ã¯ããinfo
ãwarn
ãerror
ãdebug
é¢æ°ãæã£ãŠããå¿ èŠããã
ã¹ãã¬ãŒãžã«ã¯æšæºã§JSONãã¡ã€ã«ãã¡ã¢ãªãŒãSequelizeãMongoDBãéžæã§ãããšãã話ã§ããããä»åã¯JSONãã¡ã€ã«ã«ããŸãã
migrations
ã®ããããã£ã«ããresolve
ã§ãããããã«ã¯Resolver
ãšããã€ã³ã¹ã¿ã³ã¹ãæž¡ããŸãã
ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ã®æ¡åŒµåã.js
ã.cjs
ã®å Žåã¯ç¹ã«æå®ã¯äžèŠã§ããã.ts
ã®å Žåã¯ts-node
ãã€ã³ã¹ããŒã«ããå¿
èŠãããã
.sql
ã®å Žåã¯èªåã§Resolver
ãäœæããå¿
èŠããããŸãã
https://github.com/sequelize/umzug/blob/v3.3.1/src/umzug.ts#L110-L115
ãããŠãäœæããã®ããã¡ãã§ããã
const resolver: Resolver<mysql.Connection> = (params: MigrationParams<mysql.Connection>) => ({ name: params.name, up: async () => { log(`target migration file => ${params.path}`); const sql = (await fs.readFile(params.path!)).toString(); return await params.context.query(sql); }, down: async () => { // downã¯ä»åã¯é€å€ },
name
ã§ãã€ã°ã¬ãŒã·ã§ã³åãup
ãdown
ã§ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«å®è¡æã®åŠçãèšè¿°ããŸãã
ä»åã¯ããã€ã°ã¬ãŒã·ã§ã³ã®å®è¡ã¯up
ã®ã¿å®è£
ããŸããã
up: async () => { log(`target migration file => ${params.path}`); const sql = (await fs.readFile(params.path!)).toString(); return await params.context.query(sql); },
ãŸããUmzug
ã®context
ã§æå®ããå€ã¯ããã®Resolver
ããã³MigrationParams
ã«åæ ãããããšã«ãªããŸãã
const resolver: Resolver<mysql.Connection> = (params: MigrationParams<mysql.Connection>) => ({
ãã®context
ã¯
return await params.context.query(sql);
ããã§æå®ãããªããžã§ã¯ãã§ãã
context: conn,
ããšã¯ãèŠã€ãã£ããã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãé©çšããŸãã
await umzug.up();
ãã®åã«ãé©çšæžã¿ã®ãã€ã°ã¬ãŒã·ã§ã³ãšæªé©çšã®ãã€ã°ã¬ãŒã·ã§ã³ã衚瀺ããããã«ããŸããã
// é©çšæžã¿ã®ãã€ã°ã¬ãŒã·ã§ã³ã衚瀺 const executedMetas = await umzug.executed(); if (executedMetas.length > 0) { log('current executed migrations'); for (const meta of executedMetas) { log(`executed, name = ${meta.name}, path = ${meta.path}`); } } // æªé©çšã®ãã€ã°ã¬ãŒã·ã§ã³ã衚瀺 const pendingMetas = await umzug.pending(); if (pendingMetas.length > 0) { log('current pending migrations'); for (const meta of pendingMetas) { log(`pending, name = ${meta.name}, path = ${meta.path}`); } }
ãã«ãã
$ npm run build
以éã¯ã以äžã®ã³ãã³ãã§ãã€ã°ã¬ãŒã·ã§ã³ãé©çšããŸãã
$ node dist/run-umzug.js
ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãäœæããŠãé©çšããŠã¿ã
ããã§ã¯ããã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãäœæããŠé©çšããŠãã£ãŠã¿ãŸãããã
ããŒã¿ããŒã¹ã®ç¶æ ã
MySQL localhost:3306 ssl practice SQL > show tables; Empty set (0.0044 sec)
ãŸã ããŒãã«ã¯ãããŸããã
æåã¯ããããªãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãçšæã
migrations/20231009-001.sql
create table book ( isbn varchar(14), title varchar(255), price int, primary key(isbn) );
å®è¡ã
$ node dist/run-umzug.js [2023-10-09T15:02:47.785Z] current pending migrations [2023-10-09T15:02:47.786Z] pending, name = 20231009-001.sql, path = /path/to/migrations/20231009-001.sql [2023-10-09T15:02:47.786Z] start Umzug migration... { event: 'migrating', name: '20231009-001.sql' } [2023-10-09T15:02:47.789Z] target migration file => /path/to/migrations/20231009-001.sql { event: 'migrated', name: '20231009-001.sql', durationSeconds: 0.114 } [2023-10-09T15:02:47.902Z] end Umzug migration
æªé©çšã®ãã€ã°ã¬ãŒã·ã§ã³ãåºåãããåŸããã€ã°ã¬ãŒã·ã§ã³ãé©çšãããããã§ãã
ããŒãã«ãäœæãããŠããŸãã
MySQL localhost:3306 ssl practice SQL > show tables; +--------------------+ | Tables_in_practice | +--------------------+ | book | +--------------------+ 1 row in set (0.0033 sec)
ãã®æãããã°ã©ã ãå®è¡ããã«ã¬ã³ããã£ã¬ã¯ããªã«ããã€ã°ã¬ãŒã·ã§ã³ã®ç¶æ
ãèšé²ããumzug.json
ãšãããã¡ã€ã«ãäœæãããŠããŸãã
umzug.json
[ "20231009-001.sql" ]
ã¹ãã¬ãŒãžã«ã¯JSONãéžæããŸãããããã
ããã²ãšã€ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãäœæã
migrations/20231009-002.sql
create table account ( id int, name varchar(50), registered datetime, about varchar(255), primary key(id) );
å®è¡ã
$ node dist/run-umzug.js [2023-10-09T15:06:42.802Z] current executed migrations [2023-10-09T15:06:42.802Z] executed, name = 20231009-001.sql, path = /path/to/migrations/20231009-001.sql [2023-10-09T15:06:42.804Z] current pending migrations [2023-10-09T15:06:42.804Z] pending, name = 20231009-002.sql, path = /path/to/migrations/20231009-002.sql [2023-10-09T15:06:42.804Z] start Umzug migration... { event: 'migrating', name: '20231009-002.sql' } [2023-10-09T15:06:42.806Z] target migration file => /path/to/migrations/20231009-002.sql { event: 'migrated', name: '20231009-002.sql', durationSeconds: 0.096 } [2023-10-09T15:06:42.902Z] end Umzug migration
ä»åã¯ãé©çšæžã¿ã®ãã€ã°ã¬ãŒã·ã§ã³ãšæªé©çšã®ãã€ã°ã¬ãŒã·ã§ã³ã®äž¡æ¹ã衚瀺ãããŸããã
ããŒãã«ãäœæãããããšã®ç¢ºèªã
MySQL localhost:3306 ssl practice SQL > show tables; +--------------------+ | Tables_in_practice | +--------------------+ | account | | book | +--------------------+
ã¹ãã¬ãŒãžã®ç¶æ ã
umzug.json
[ "20231009-001.sql", "20231009-002.sql" ]
ããŒã¿ãç»é²ãããã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãçšæããŠã¿ãŸãããã
migrations/20231009-003.sql
insert into book(isbn, title, price) values('978-4798161488', 'MySQL培åºå ¥é 第4ç MySQL 8.0察å¿', 4180); insert into book(isbn, title, price) values('978-4798147406', '詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã', 3960); insert into book(isbn, title, price) values('978-4873116389', 'å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç', 5280);
å®è¡ã
$ node dist/run-umzug.js [2023-10-09T15:09:24.388Z] current executed migrations [2023-10-09T15:09:24.388Z] executed, name = 20231009-001.sql, path = /path/to/migrations/20231009-001.sql [2023-10-09T15:09:24.388Z] executed, name = 20231009-002.sql, path = /path/to/migrations/20231009-002.sql [2023-10-09T15:09:24.390Z] current pending migrations [2023-10-09T15:09:24.390Z] pending, name = 20231009-003.sql, path = /path/to/migrations/20231009-003.sql [2023-10-09T15:09:24.390Z] start Umzug migration... { event: 'migrating', name: '20231009-003.sql' } [2023-10-09T15:09:24.393Z] target migration file => /path/to/migrations/20231009-003.sql { event: 'migrated', name: '20231009-003.sql', durationSeconds: 0.07 } [2023-10-09T15:09:24.462Z] end Umzug migration
ããŒã¿ãå ¥ããŸããã
MySQL localhost:3306 ssl practice SQL > select * from book; +----------------+------------------------------------------------------------------------------------------+-------+ | isbn | title | price | +----------------+------------------------------------------------------------------------------------------+-------+ | 978-4798147406 | 詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã | 3960 | | 978-4798161488 | MySQL培åºå ¥é 第4ç MySQL 8.0å¯Ÿå¿ | 4180 | | 978-4873116389 | å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç | 5280 | +----------------+------------------------------------------------------------------------------------------+-------+ 3 rows in set (0.0011 sec)
ã¹ãã¬ãŒãžã®ç¶æ ã
umzug.json
[ "20231009-001.sql", "20231009-002.sql", "20231009-003.sql" ]
倱æãããã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãäœæãããšãã©ããªãã®ã§ããããïŒ
SQLãšããŠèª€ã£ããã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãäœæã
migrations/20231009-004.sql
invalid sql statement
å®è¡ããŠã¿ãŸãã
dist/run-umzug.js [2023-10-09T15:11:30.622Z] current executed migrations [2023-10-09T15:11:30.622Z] executed, name = 20231009-001.sql, path = /path/to/migrations/20231009-001.sql [2023-10-09T15:11:30.622Z] executed, name = 20231009-002.sql, path = /path/to/migrations/20231009-002.sql [2023-10-09T15:11:30.622Z] executed, name = 20231009-003.sql, path = /path/to/migrations/20231009-003.sql [2023-10-09T15:11:30.624Z] current pending migrations [2023-10-09T15:11:30.624Z] pending, name = 20231009-004.sql, path = /path/to/migrations/20231009-004.sql [2023-10-09T15:11:30.624Z] start Umzug migration... { event: 'migrating', name: '20231009-004.sql' } [2023-10-09T15:11:30.627Z] target migration file => /path/to/migrations/20231009-004.sql MigrationError: Migration 20231009-004.sql (up) failed: Original 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 'invalid sql statement' at line 1 at /path/to/node_modules/umzug/lib/umzug.js:151:27 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Umzug.runCommand (/path/to/node_modules/umzug/lib/umzug.js:107:20) at async main (/path/to/dist/run-umzug.js:53:9) { cause: 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 'invalid sql statement' at line 1 at PromiseConnection.query (/path/to/node_modules/mysql2/promise.js:94:22) at Object.up (/path/to/dist/run-umzug.js:24:45) at async /path/to/node_modules/umzug/lib/umzug.js:148:21 at async Umzug.runCommand (/path/to/node_modules/umzug/lib/umzug.js:107:20) at async main (/path/to/dist/run-umzug.js:53:9) { code: 'ER_PARSE_ERROR', errno: 1064, sql: 'invalid sql statement\n', sqlState: '42000', 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 'invalid sql statement' at line 1" }, jse_cause: 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 'invalid sql statement' at line 1 at PromiseConnection.query (/path/to/node_modules/mysql2/promise.js:94:22) at Object.up (/path/to/dist/run-umzug.js:24:45) at async /path/to/node_modules/umzug/lib/umzug.js:148:21 at async Umzug.runCommand (/path/to/node_modules/umzug/lib/umzug.js:107:20) at async main (/path/to/dist/run-umzug.js:53:9) { code: 'ER_PARSE_ERROR', errno: 1064, sql: 'invalid sql statement\n', sqlState: '42000', 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 'invalid sql statement' at line 1" }, migration: { direction: 'up', name: '20231009-004.sql', path: '/path/to/migrations/20231009-004.sql', context: PromiseConnection { _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, connection: [Connection], Promise: [Function: Promise], [Symbol(kCapture)]: false } } }
åœç¶ã§ãããå®è¡ã«å€±æããŸããæ§æãšã©ãŒã§ããã
ãã®æã®ã¹ãã¬ãŒãžã®ç¶æ ã§ããã倱æãããã€ã°ã¬ãŒã·ã§ã³ã¯èšé²ãããŠããŸããã
umzug.json
[ "20231009-001.sql", "20231009-002.sql", "20231009-003.sql" ]
ãªã®ã§ããã1床ããã°ã©ã ãå®è¡ããããšãããšãå床ãã®ãã€ã°ã¬ãŒã·ã§ã³ãé©çšããããšããŸãïŒä¿®æ£ãããŸã§ã¯æåããŸãããïŒã
ãšããããããããªãšããããªãšæããŸããCLIãè©ŠããŠã¿ããã£ãæ°ãããŸãããSQLãã¡ã€ã«ã¯ãã®æãã ãšããã°ã©ã ã§Resolver
ã
äœæããªããšãããªãæ°ãããã®ã§ãä»åã¯ããã§ãããã
ãããã«
Node.jsã®ãã€ã°ã¬ãŒã·ã§ã³ããŒã«ã§ãããUmzugãè©ŠããŠã¿ãŸããã
ãã€ã°ã¬ãŒã·ã§ã³ã®ããã«ãœãŒã¹ã³ãŒããæžããšããããšããã£ãããšããªãã£ãã®ã§ãã¡ãã£ãšæ°é®®ã§ããã
æšæºã§Sequelizeçµç±ä»¥å€ã§ããŒã¿ããŒã¹ãã¹ãã¬ãŒãžã«ã§ãããšããã£ãæ°ã¯ããŸãããâŠã
db-migrateã®æ¹ã ãšã³ãã³ãã§SQLãŸã§å®è¡ã§ãããããªé°å²æ°ã§ãããæ°ãåãããèŠãŠã¿ããããããŸããã