Updated angel3 migration

This commit is contained in:
Thomas Hii 2024-07-20 10:23:45 +08:00
parent cb25da3077
commit 7e42a7e317
14 changed files with 176 additions and 44 deletions

View file

@ -30,12 +30,12 @@ The required applications by the framework can be run using the docker compose f
psql --username postgres psql --username postgres
``` ```
### Create database, user and access ### Create PostgreSQL database, user and grant access
```psql ```sql
postgres=# create database orm_test; create database orm_test;
postgres=# create user test with encrypted password 'test123'; create user test with encrypted password 'test123';
postgres=# grant all privileges on database orm_test to test; grant all privileges on database orm_test to test;
``` ```
## MariaDB ## MariaDB
@ -59,6 +59,20 @@ The required applications by the framework can be run using the docker compose f
docker logs maria-mariadb-1 -f docker logs maria-mariadb-1 -f
``` ```
### Create MariaDB database, user and grant access
```sql
create database orm_test;
-- Granting localhost access only
create user 'test'@'localhost' identified by 'test123';
grant all privileges on orm_test.* to 'test'@'localhost';
-- Granting localhost and remote access
create user 'test'@'%' identified by 'test123';
grant all privileges on orm_test.* to 'test'@'%';
```
## MySQL ## MySQL
### Starting the MySQL container ### Starting the MySQL container
@ -80,6 +94,20 @@ The required applications by the framework can be run using the docker compose f
docker logs mysql-mysql-1 -f docker logs mysql-mysql-1 -f
``` ```
### Create MySQL database, user and grant access
```sql
create database orm_test;
-- Granting localhost access only
create user 'test'@'localhost' identified by 'test123';
grant all privileges on orm_test.* to 'test'@'localhost';
-- Granting localhost and remote access
create user 'test'@'%' identified by 'test123';
grant all privileges on orm_test.* to 'test'@'%';
```
## MongoDB ## MongoDB
### Starting the MongoDB container ### Starting the MongoDB container

View file

@ -10,7 +10,7 @@ services:
volumes: volumes:
- "db:/var/lib/postgresql/data" - "db:/var/lib/postgresql/data"
networks: networks:
- webnet - appnet
pgadmin4: pgadmin4:
image: dpage/pgadmin4:latest image: dpage/pgadmin4:latest

View file

@ -3,6 +3,7 @@
## 8.2.1 ## 8.2.1
* Updated README * Updated README
* Updated examples
* Added test cases for `PostgreSQL` * Added test cases for `PostgreSQL`
* Added test cases for `MySQL` * Added test cases for `MySQL`
* Added test cases for `MariaDB` * Added test cases for `MariaDB`

View file

@ -2,13 +2,23 @@ import 'dart:io';
import 'package:angel3_migration/angel3_migration.dart'; import 'package:angel3_migration/angel3_migration.dart';
import 'package:angel3_migration_runner/angel3_migration_runner.dart'; import 'package:angel3_migration_runner/angel3_migration_runner.dart';
import 'package:angel3_migration_runner/mysql.dart';
import 'package:angel3_migration_runner/postgres.dart'; import 'package:angel3_migration_runner/postgres.dart';
import 'package:angel3_orm/angel3_orm.dart'; import 'package:angel3_orm/angel3_orm.dart';
import 'package:mysql_client/mysql_client.dart';
import 'package:postgres/postgres.dart'; import 'package:postgres/postgres.dart';
import 'todo.dart'; import 'todo.dart';
void main(List<String> args) async { void main(List<String> args) async {
// Run migration on PostgreSQL database
postgresqlMigration(args);
// Run migration on MySQL database
mysqlMigration(args);
}
void postgresqlMigration(List<String> args) async {
var host = Platform.environment['DB_HOST'] ?? 'localhost'; var host = Platform.environment['DB_HOST'] ?? 'localhost';
var database = Platform.environment['DB_NAME'] ?? 'demo'; var database = Platform.environment['DB_NAME'] ?? 'demo';
var username = Platform.environment['DB_USERNAME'] ?? 'demouser'; var username = Platform.environment['DB_USERNAME'] ?? 'demouser';
@ -16,14 +26,16 @@ void main(List<String> args) async {
print("$host $database $username $password"); print("$host $database $username $password");
Connection conn = await Connection.open(Endpoint( Connection conn = await Connection.open(
host: host, Endpoint(
port: 5432, host: host,
database: database, port: 5432,
username: username, database: database,
password: password)); username: username,
password: password),
settings: ConnectionSettings(sslMode: SslMode.disable));
var postgresqlMigrationRunner = PostgresMigrationRunner( var runner = PostgresMigrationRunner(
conn, conn,
migrations: [ migrations: [
UserMigration(), UserMigration(),
@ -32,17 +44,25 @@ void main(List<String> args) async {
], ],
); );
/* runMigrations(runner, args);
}
void mysqlMigration(List<String> args) async {
var host = Platform.environment['MYSQL_HOST'] ?? 'localhost';
var database = Platform.environment['MYSQL_DB'] ?? 'orm_test';
var username = Platform.environment['MYSQL_USERNAME'] ?? 'test';
var password = Platform.environment['MYSQL_PASSWORD'] ?? 'test123';
var mySQLConn = await MySQLConnection.createConnection( var mySQLConn = await MySQLConnection.createConnection(
host: host, host: host,
port: 3306, port: 3306,
databaseName: database, databaseName: database,
userName: username, userName: username,
password: password, password: password,
secure: false); secure: true);
// ignore: unused_local_variable // ignore: unused_local_variable
var mysqlMigrationRunner = MySqlMigrationRunner( var runner = MySqlMigrationRunner(
mySQLConn, mySQLConn,
migrations: [ migrations: [
UserMigration(), UserMigration(),
@ -50,9 +70,8 @@ void main(List<String> args) async {
FooMigration(), FooMigration(),
], ],
); );
*/
runMigrations(postgresqlMigrationRunner, args); runMigrations(runner, args);
} }
class FooMigration extends Migration { class FooMigration extends Migration {

View file

@ -7,6 +7,7 @@ import '../runner.dart';
import '../util.dart'; import '../util.dart';
import 'schema.dart'; import 'schema.dart';
/// A MariaDB database migration runner.
class MariaDbMigrationRunner implements MigrationRunner { class MariaDbMigrationRunner implements MigrationRunner {
final _log = Logger('MariaDbMigrationRunner'); final _log = Logger('MariaDbMigrationRunner');

View file

@ -5,6 +5,7 @@ import 'package:mysql1/mysql1.dart';
import 'table.dart'; import 'table.dart';
/// A MariaDB database schema generator
class MariaDbSchema extends Schema { class MariaDbSchema extends Schema {
final _log = Logger('MariaDbSchema'); final _log = Logger('MariaDbSchema');

View file

@ -7,6 +7,7 @@ import '../runner.dart';
import '../util.dart'; import '../util.dart';
import 'schema.dart'; import 'schema.dart';
/// A MySQL database migration runner.
class MySqlMigrationRunner implements MigrationRunner { class MySqlMigrationRunner implements MigrationRunner {
final _log = Logger('MysqlMigrationRunner'); final _log = Logger('MysqlMigrationRunner');

View file

@ -5,6 +5,7 @@ import 'package:mysql_client/mysql_client.dart';
import 'table.dart'; import 'table.dart';
/// A MySQL database schema generator
class MySqlSchema extends Schema { class MySqlSchema extends Schema {
final _log = Logger('MysqlSchema'); final _log = Logger('MysqlSchema');

View file

@ -7,6 +7,7 @@ import '../runner.dart';
import '../util.dart'; import '../util.dart';
import 'schema.dart'; import 'schema.dart';
/// A PostgreSQL database migration runner
class PostgresMigrationRunner implements MigrationRunner { class PostgresMigrationRunner implements MigrationRunner {
final _log = Logger('PostgresMigrationRunner'); final _log = Logger('PostgresMigrationRunner');
@ -17,8 +18,10 @@ class PostgresMigrationRunner implements MigrationRunner {
PostgresMigrationRunner(this.connection, PostgresMigrationRunner(this.connection,
{Iterable<Migration> migrations = const [], bool connected = false}) { {Iterable<Migration> migrations = const [], bool connected = false}) {
if (migrations.isNotEmpty == true) migrations.forEach(addMigration); if (migrations.isNotEmpty) {
_connected = connected == true; migrations.forEach(addMigration);
}
_connected = connected;
} }
@override @override
@ -26,17 +29,16 @@ class PostgresMigrationRunner implements MigrationRunner {
_migrationQueue.addLast(migration); _migrationQueue.addLast(migration);
} }
Future _init() async { Future<void> _init() async {
while (_migrationQueue.isNotEmpty) { while (_migrationQueue.isNotEmpty) {
var migration = _migrationQueue.removeFirst(); var migration = _migrationQueue.removeFirst();
var path = await absoluteSourcePath(migration.runtimeType); var path = await absoluteSourcePath(migration.runtimeType);
migrations.putIfAbsent(path.replaceAll('\\', '\\\\'), () => migration); migrations.putIfAbsent(path.replaceAll('\\', '\\\\'), () => migration);
} }
_connected = connection.isOpen;
if (!_connected) { if (!_connected) {
//await connection.open(); throw Exception("PostgreSQL connection is not open");
//Connection.open(_endpoint!, settings: _settings);
_connected = true;
} }
await connection.execute(''' await connection.execute('''
@ -47,9 +49,10 @@ class PostgresMigrationRunner implements MigrationRunner {
PRIMARY KEY(id) PRIMARY KEY(id)
); );
''').then((result) { ''').then((result) {
_log.info('Check and create "migrations" table'); _log.info('Created "migrations" table');
}).catchError((e) { }).catchError((e) {
_log.severe('Failed to create "migrations" table.'); _log.severe('Failed to create "migrations" table.');
throw e;
}); });
} }
@ -73,8 +76,8 @@ class PostgresMigrationRunner implements MigrationRunner {
var migration = migrations[k]!; var migration = migrations[k]!;
var schema = PostgresSchema(); var schema = PostgresSchema();
migration.up(schema); migration.up(schema);
_log.info('Added "$k" into "migrations" table.');
await schema.run(connection).then((_) { var result = await schema.run(connection).then((_) {
return connection.runTx((ctx) async { return connection.runTx((ctx) async {
var result = await ctx.execute( var result = await ctx.execute(
"INSERT INTO MIGRATIONS (batch, path) VALUES ($batch, '$k')"); "INSERT INTO MIGRATIONS (batch, path) VALUES ($batch, '$k')");
@ -85,6 +88,9 @@ class PostgresMigrationRunner implements MigrationRunner {
_log.severe('Failed to insert into "migrations" table.'); _log.severe('Failed to insert into "migrations" table.');
return -1; return -1;
}); });
if (result > 0) {
_log.info('Inserted "$k" into "migrations" table.');
}
} }
} else { } else {
_log.warning('Nothing to add into "migrations" table.'); _log.warning('Nothing to add into "migrations" table.');

View file

@ -4,6 +4,7 @@ import 'package:postgres/postgres.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'table.dart'; import 'table.dart';
/// A PostgreSQL database schema generator
class PostgresSchema extends Schema { class PostgresSchema extends Schema {
final _log = Logger('PostgresSchema'); final _log = Logger('PostgresSchema');

View file

@ -1,12 +1,19 @@
import 'dart:io'; import 'dart:io';
import 'package:angel3_migration_runner/angel3_migration_runner.dart';
import 'package:angel3_migration_runner/mariadb.dart';
import 'package:mysql1/mysql1.dart'; import 'package:mysql1/mysql1.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'models/todo.dart';
void main() async { void main() async {
late MySqlConnection conn; late MySqlConnection conn;
late MigrationRunner runner;
setUp(() async { setUp(() async {
print("Setup...");
var host = Platform.environment['MYSQL_HOST'] ?? 'localhost'; var host = Platform.environment['MYSQL_HOST'] ?? 'localhost';
var database = Platform.environment['MYSQL_DB'] ?? 'orm_test'; var database = Platform.environment['MYSQL_DB'] ?? 'orm_test';
var username = Platform.environment['MYSQL_USERNAME'] ?? 'test'; var username = Platform.environment['MYSQL_USERNAME'] ?? 'test';
@ -19,13 +26,26 @@ void main() async {
user: username, user: username,
password: password); password: password);
conn = await MySqlConnection.connect(settings); conn = await MySqlConnection.connect(settings);
runner = MariaDbMigrationRunner(
conn,
migrations: [
UserMigration(),
TodoMigration(),
ItemMigration(),
],
);
}); });
group('MariaDB', () { group('MariaDB', () {
test('migrate tables', () async {}); test('migrate tables', () async {
print("Test migration up");
runner.up();
});
}); });
tearDown(() async { tearDown(() async {
print("Teardown...");
await conn.close(); await conn.close();
}); });
} }

View file

@ -1,19 +1,26 @@
import 'dart:io'; import 'dart:io';
import 'package:angel3_migration_runner/angel3_migration_runner.dart';
import 'package:angel3_migration_runner/mysql.dart';
import 'package:mysql_client/mysql_client.dart'; import 'package:mysql_client/mysql_client.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'models/todo.dart';
void main() async { void main() async {
late MySQLConnection conn; late MySQLConnection conn;
late MigrationRunner runner;
setUp(() async { setUp(() async {
print("Setup...");
var host = Platform.environment['MYSQL_HOST'] ?? 'localhost'; var host = Platform.environment['MYSQL_HOST'] ?? 'localhost';
var database = Platform.environment['MYSQL_DB'] ?? 'orm_test'; var database = Platform.environment['MYSQL_DB'] ?? 'orm_test';
var username = Platform.environment['MYSQL_USERNAME'] ?? 'test'; var username = Platform.environment['MYSQL_USERNAME'] ?? 'test';
var password = Platform.environment['MYSQL_PASSWORD'] ?? 'test123'; var password = Platform.environment['MYSQL_PASSWORD'] ?? 'test123';
var secure = !('false' == Platform.environment['MYSQL_SECURE']); //var secure = !('false' == Platform.environment['MYSQL_SECURE']);
print("$host $database $username $password $secure"); print("$host $database $username $password");
conn = await MySQLConnection.createConnection( conn = await MySQLConnection.createConnection(
databaseName: database, databaseName: database,
@ -21,14 +28,31 @@ void main() async {
host: host, host: host,
userName: username, userName: username,
password: password, password: password,
secure: secure); secure: true);
await conn.connect();
runner = MySqlMigrationRunner(
conn,
migrations: [
UserMigration(),
TodoMigration(),
ItemMigration(),
],
);
}); });
group('Mysql', () { group('Mysql migrate tables', () {
test('migrate tables', () async {}); test('up', () async {
print("Test migration up");
await runner.up();
});
}); });
tearDown(() async { tearDown(() async {
await conn.close(); print("Teardown...");
if (conn.connected) {
await conn.close();
}
}); });
} }

View file

@ -1,32 +1,59 @@
import 'dart:io'; import 'dart:io';
import 'package:angel3_migration_runner/angel3_migration_runner.dart';
import 'package:angel3_migration_runner/postgres.dart';
import 'package:postgres/postgres.dart'; import 'package:postgres/postgres.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'models/todo.dart';
void main() async { void main() async {
late Connection conn; late Connection conn;
late MigrationRunner runner;
setUp(() async { setUp(() async {
print("Setup...");
var host = Platform.environment['POSTGRES_HOST'] ?? 'localhost'; var host = Platform.environment['POSTGRES_HOST'] ?? 'localhost';
var database = Platform.environment['POSTGRES_DB'] ?? 'orm_test'; var database = Platform.environment['POSTGRES_DB'] ?? 'orm_test';
var username = Platform.environment['POSTGRES_USERNAME'] ?? 'test'; var username = Platform.environment['POSTGRES_USERNAME'] ?? 'test';
var password = Platform.environment['POSTGRES_PASSWORD'] ?? 'test123'; var password = Platform.environment['POSTGRES_PASSWORD'] ?? 'test123';
print("$host $database $username $password"); //print("$host $database $username $password");
conn = await Connection.open(Endpoint( conn = await Connection.open(
host: host, Endpoint(
port: 5432, host: host,
database: database, port: 5432,
username: username, database: database,
password: password)); username: username,
password: password),
settings: ConnectionSettings(sslMode: SslMode.disable));
runner = PostgresMigrationRunner(
conn,
migrations: [
UserMigration(),
TodoMigration(),
ItemMigration(),
],
);
}); });
group('PostgreSQL', () { group('PostgreSQL migrate tables', () {
test('migrate tables', () async {}); test('up', () async {
print("Test migration up");
await runner.up();
});
test('reset', () async {
print("Test migration reset");
await runner.reset();
});
}); });
tearDown(() async { tearDown(() async {
print("Teardown...");
await conn.close(); await conn.close();
}); });
} }

View file

@ -89,7 +89,9 @@ Future<PostgreSqlPoolExecutor> connectToPostgresPool(
) )
], ],
settings: PoolSettings( settings: PoolSettings(
maxConnectionAge: Duration(hours: 1), maxConnectionCount: 5)); maxConnectionAge: Duration(hours: 1),
maxConnectionCount: 5,
sslMode: SslMode.disable));
// Run sql to create the tables in a transaction // Run sql to create the tables in a transaction
await dbPool.runTx((conn) async { await dbPool.runTx((conn) async {