Fixed migration runner for MySQL

This commit is contained in:
thomashii@dukefirehawk.com 2022-07-27 22:21:36 +08:00
parent aff68b2f07
commit 98dfef8e33
5 changed files with 79 additions and 42 deletions

View file

@ -5,6 +5,8 @@
* Upgraded to `lints` 2.x.x * Upgraded to `lints` 2.x.x
* Fixed issue #70. Incorrectly generated SQL for `defaultsTo('Default Value')` * Fixed issue #70. Incorrectly generated SQL for `defaultsTo('Default Value')`
* Mapped timestamp to datetime for MySQL and MariaDB * Mapped timestamp to datetime for MySQL and MariaDB
* Fixed `MariaDbMigrationRunner` to work with MariaDB
* Fixed `MySqlMigrationRunner` to work with MySQL and MariaDB
## 6.0.1 ## 6.0.1

View file

@ -9,14 +9,20 @@ Database migration runner for Angel3 ORM.
Supported database: Supported database:
* PostgreSQL version 10 or later * PostgreSQL 10.x or greater
* MariaDB 10.2.x or later * MariaDB 10.2.x or greater
* MySQL 8.x or later * MySQL 8.x or greater
## Usage ## Usage
* Use `PostgresMigrationRunner` to perform the database migration for PostgreSQL. * Use `PostgresMigrationRunner` to perform database migration for PostgreSQL.
* Use `MySqlMigrationRunner` to perform the database migration for MySQL and MariaDB. This is implemented with [`mysql_client`](https://pub.dev/packages?q=mysql_client) driver. * Use `MySqlMigrationRunner` to perform database migration for MySQL and MariaDB. This runner is using [`mysql_client`](https://pub.dev/packages?q=mysql_client) driver.
* Use `MariaDbMigrationRunner` to perform the database migration for MariaDB. [`mysql1`](https://pub.dev/packages?q=mysql1). * Use `MariaDbMigrationRunner` to perform database migration for MariaDB. This runner is using[`mysql1`](https://pub.dev/packages?q=mysql1) driver.
## Supported Operations
* reset - Clear out all records in the `migrations` table and drop all the managed ORM tables.
* up - Generate all the managed ORM tables based on the ORM models.
* refresh - Run `reset` follow by `up`

View file

@ -45,7 +45,7 @@ class MariaDbMigrationRunner implements MigrationRunner {
PRIMARY KEY(id) PRIMARY KEY(id)
); );
''').then((result) { ''').then((result) {
_log.info('Check and create "migrations" table'); _log.fine('Check and create "migrations" table');
}).catchError((e) { }).catchError((e) {
_log.severe('Failed to create "migrations" table.', e); _log.severe('Failed to create "migrations" table.', e);
}); });
@ -54,18 +54,25 @@ class MariaDbMigrationRunner implements MigrationRunner {
@override @override
Future up() async { Future up() async {
await _init(); await _init();
var r = await connection.query('SELECT path from migrations;'); var result = await connection.query('SELECT path from migrations;');
var existing = r.expand((x) => x).cast<String>();
var toRun = <String>[];
var existing = <String>[];
if (result.isNotEmpty) {
existing = result.expand((x) => x).cast<String>().toList();
}
var toRun = <String>[];
migrations.forEach((k, v) { migrations.forEach((k, v) {
if (!existing.contains(k)) toRun.add(k); if (!existing.contains(k)) toRun.add(k);
}); });
if (toRun.isNotEmpty) { if (toRun.isNotEmpty) {
var r = await connection.query('SELECT MAX(batch) from migrations;'); var result = await connection.query('SELECT MAX(batch) from migrations;');
var rTmp = r.toList(); var curBatch = 0;
var curBatch = int.tryParse(rTmp[0][0] ?? '0') as int; if (result.isNotEmpty) {
var firstRow = result.toList();
curBatch = int.tryParse(firstRow[0][0] ?? '0') as int;
}
var batch = curBatch + 1; var batch = curBatch + 1;
for (var k in toRun) { for (var k in toRun) {
@ -73,11 +80,10 @@ class MariaDbMigrationRunner implements MigrationRunner {
var schema = MariaDbSchema(); var schema = MariaDbSchema();
migration.up(schema); migration.up(schema);
_log.info('Added "$k" into "migrations" table.'); _log.info('Added "$k" into "migrations" table.');
try { try {
await schema.run(connection).then((_) async { await schema.run(connection).then((_) async {
var result = await connection.query( var result = await connection.query(
"INSERT INTO MIGRATIONS (batch, path) VALUES ($batch, '$k')"); "INSERT INTO migrations (batch, path) VALUES ($batch, '$k')");
return result.affectedRows; return result.affectedRows;
}); });
@ -94,13 +100,21 @@ class MariaDbMigrationRunner implements MigrationRunner {
Future rollback() async { Future rollback() async {
await _init(); await _init();
var r = await connection.query('SELECT MAX(batch) from migrations;'); var result = await connection.query('SELECT MAX(batch) from migrations;');
var rTmp = r.toList();
var curBatch = int.tryParse(rTmp[0][0] ?? 0) as int;
r = await connection var curBatch = 0;
if (result.isNotEmpty) {
var firstRow = result.toList();
curBatch = int.tryParse(firstRow[0][0]) as int;
}
result = await connection
.query('SELECT path from migrations WHERE batch = $curBatch;'); .query('SELECT path from migrations WHERE batch = $curBatch;');
var existing = r.expand((x) => x).cast<String>(); var existing = <String>[];
if (result.isNotEmpty) {
existing = result.expand((x) => x).cast<String>().toList();
}
var toRun = <String>[]; var toRun = <String>[];
migrations.forEach((k, v) { migrations.forEach((k, v) {
@ -128,7 +142,11 @@ class MariaDbMigrationRunner implements MigrationRunner {
await _init(); await _init();
var r = await connection var r = await connection
.query('SELECT path from migrations ORDER BY batch DESC;'); .query('SELECT path from migrations ORDER BY batch DESC;');
var existing = r.expand((x) => x).cast<String>(); var existing = <String>[];
if (r.isNotEmpty) {
existing = r.expand((x) => x).cast<String>().toList();
}
var toRun = existing.where(migrations.containsKey).toList(); var toRun = existing.where(migrations.containsKey).toList();
if (toRun.isNotEmpty) { if (toRun.isNotEmpty) {

View file

@ -42,7 +42,7 @@ class MariaDbSchema extends Schema {
@override @override
void drop(String tableName, {bool cascade = false}) { void drop(String tableName, {bool cascade = false}) {
var c = cascade == true ? ' CASCADE' : ''; var c = cascade == true ? ' CASCADE' : '';
_writeln('DROP TABLE "$tableName"$c;'); _writeln('DROP TABLE $tableName$c;');
} }
@override @override

View file

@ -54,8 +54,11 @@ class MySqlMigrationRunner implements MigrationRunner {
@override @override
Future up() async { Future up() async {
await _init(); await _init();
var r = await connection.execute('SELECT path from migrations;'); var result = await connection.execute('SELECT path from migrations;');
var existing = r.rows.cast<String>(); //.expand((x) => x).cast<String>(); var existing = <String>[];
if (result.rows.isNotEmpty) {
existing = result.rows.first.assoc().values.cast<String>().toList();
}
var toRun = <String>[]; var toRun = <String>[];
migrations.forEach((k, v) { migrations.forEach((k, v) {
@ -63,11 +66,14 @@ class MySqlMigrationRunner implements MigrationRunner {
}); });
if (toRun.isNotEmpty) { if (toRun.isNotEmpty) {
var r = await connection.execute('SELECT MAX(batch) from migrations;'); var result =
var rTmp = r.rows.first; //r.toList(); await connection.execute('SELECT MAX(batch) from migrations;');
var curBatch = var curBatch = 0;
int.tryParse(rTmp.colAt(0) ?? "0") ?? 0; //(rTmp[0][0] ?? 0) as int; if (result.rows.isNotEmpty) {
var batch = curBatch + 1; var firstRow = result.rows.first;
curBatch = int.tryParse(firstRow.colAt(0) ?? "0") ?? 0;
}
curBatch++;
for (var k in toRun) { for (var k in toRun) {
var migration = migrations[k]!; var migration = migrations[k]!;
@ -77,16 +83,13 @@ class MySqlMigrationRunner implements MigrationRunner {
await schema.run(connection).then((_) async { await schema.run(connection).then((_) async {
var result = await connection var result = await connection
.execute( .execute(
"INSERT INTO MIGRATIONS (batch, path) VALUES ($batch, '$k')") "INSERT INTO migrations (batch, path) VALUES ($curBatch, '$k')")
.catchError((e) { .catchError((e) {
_log.severe('Failed to insert into "migrations" table.', e); _log.severe('Failed to insert into "migrations" table.', e);
}); });
return result.affectedRows.toInt(); return result.affectedRows.toInt();
}); });
//return connection.execute(
// 'INSERT INTO MIGRATIONS (batch, path) VALUES ($batch, \'$k\');');
} }
} else { } else {
_log.warning('Nothing to add into "migrations" table.'); _log.warning('Nothing to add into "migrations" table.');
@ -97,14 +100,18 @@ class MySqlMigrationRunner implements MigrationRunner {
Future rollback() async { Future rollback() async {
await _init(); await _init();
var r = await connection.execute('SELECT MAX(batch) from migrations;'); var result = await connection.execute('SELECT MAX(batch) from migrations;');
var rTmp = r.rows.first; //r.toList(); var curBatch = 0;
var curBatch = if (result.rows.isNotEmpty) {
int.tryParse(rTmp.colAt(0) ?? "0") ?? 0; //(rTmp[0][0] ?? 0) as int; var firstRow = result.rows.first;
curBatch = int.tryParse(firstRow.colAt(0) ?? "0") ?? 0;
r = await connection }
result = await connection
.execute('SELECT path from migrations WHERE batch = $curBatch;'); .execute('SELECT path from migrations WHERE batch = $curBatch;');
var existing = r.rows.cast<String>(); //r.expand((x) => x).cast<String>(); var existing = <String>[];
if (result.rows.isNotEmpty) {
existing = result.rows.first.assoc().values.cast<String>().toList();
}
var toRun = <String>[]; var toRun = <String>[];
migrations.forEach((k, v) { migrations.forEach((k, v) {
@ -130,9 +137,13 @@ class MySqlMigrationRunner implements MigrationRunner {
@override @override
Future reset() async { Future reset() async {
await _init(); await _init();
var r = await connection var result = await connection
.execute('SELECT path from migrations ORDER BY batch DESC;'); .execute('SELECT path from migrations ORDER BY batch DESC;');
var existing = r.rows.cast<String>(); //r.expand((x) => x).cast<String>(); var existing = <String>[];
if (result.rows.isNotEmpty) {
var firstRow = result.rows.first;
existing = firstRow.assoc().values.cast<String>().toList();
}
var toRun = existing.where(migrations.containsKey).toList(); var toRun = existing.where(migrations.containsKey).toList();
if (toRun.isNotEmpty) { if (toRun.isNotEmpty) {