Published migration_runner
This commit is contained in:
parent
d2eb602b2d
commit
88bdabc5c9
10 changed files with 85 additions and 64 deletions
|
@ -1,4 +1,4 @@
|
|||
# 4.0.0
|
||||
# 4.0.0-beta.1
|
||||
* Migrated to support Dart SDK 2.12.x NNBD
|
||||
|
||||
# 3.0.0
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
# migration
|
||||
# angel3_migration_runner
|
||||
[![version](https://img.shields.io/badge/pub-v4.0.0-brightgreen)](https://pub.dartlang.org/packages/angel3_migration_runner)
|
||||
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
||||
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
|
||||
|
||||
[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/orm/angel_migration_runner/LICENSE)
|
||||
|
||||
A PostgreSQL database migration framework built on Angel's ORM.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
include: package:pedantic/analysis_options.yaml
|
||||
analyzer:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
|
@ -4,24 +4,26 @@ import 'runner.dart';
|
|||
|
||||
/// Runs the Angel Migration CLI.
|
||||
Future runMigrations(MigrationRunner migrationRunner, List<String> args) {
|
||||
var cmd = new CommandRunner('migration_runner', 'Executes Angel migrations.')
|
||||
..addCommand(new _UpCommand(migrationRunner))
|
||||
..addCommand(new _RefreshCommand(migrationRunner))
|
||||
..addCommand(new _ResetCommand(migrationRunner))
|
||||
..addCommand(new _RollbackCommand(migrationRunner));
|
||||
var cmd = CommandRunner('migration_runner', 'Executes Angel migrations.')
|
||||
..addCommand(_UpCommand(migrationRunner))
|
||||
..addCommand(_RefreshCommand(migrationRunner))
|
||||
..addCommand(_ResetCommand(migrationRunner))
|
||||
..addCommand(_RollbackCommand(migrationRunner));
|
||||
return cmd.run(args).then((_) => migrationRunner.close());
|
||||
}
|
||||
|
||||
class _UpCommand extends Command {
|
||||
_UpCommand(this.migrationRunner);
|
||||
|
||||
@override
|
||||
String get name => 'up';
|
||||
@override
|
||||
String get description => 'Runs outstanding migrations.';
|
||||
|
||||
final MigrationRunner migrationRunner;
|
||||
|
||||
@override
|
||||
run() {
|
||||
Future run() {
|
||||
return migrationRunner.up();
|
||||
}
|
||||
}
|
||||
|
@ -29,13 +31,15 @@ class _UpCommand extends Command {
|
|||
class _ResetCommand extends Command {
|
||||
_ResetCommand(this.migrationRunner);
|
||||
|
||||
@override
|
||||
String get name => 'reset';
|
||||
@override
|
||||
String get description => 'Resets the database.';
|
||||
|
||||
final MigrationRunner migrationRunner;
|
||||
|
||||
@override
|
||||
run() {
|
||||
Future run() {
|
||||
return migrationRunner.reset();
|
||||
}
|
||||
}
|
||||
|
@ -43,14 +47,16 @@ class _ResetCommand extends Command {
|
|||
class _RefreshCommand extends Command {
|
||||
_RefreshCommand(this.migrationRunner);
|
||||
|
||||
@override
|
||||
String get name => 'refresh';
|
||||
@override
|
||||
String get description =>
|
||||
'Resets the database, and then re-runs all migrations.';
|
||||
|
||||
final MigrationRunner migrationRunner;
|
||||
|
||||
@override
|
||||
run() {
|
||||
Future run() {
|
||||
return migrationRunner.reset().then((_) => migrationRunner.up());
|
||||
}
|
||||
}
|
||||
|
@ -58,13 +64,15 @@ class _RefreshCommand extends Command {
|
|||
class _RollbackCommand extends Command {
|
||||
_RollbackCommand(this.migrationRunner);
|
||||
|
||||
@override
|
||||
String get name => 'rollback';
|
||||
@override
|
||||
String get description => 'Undoes the last batch of migrations.';
|
||||
|
||||
final MigrationRunner migrationRunner;
|
||||
|
||||
@override
|
||||
run() {
|
||||
Future run() {
|
||||
return migrationRunner.rollback();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'package:angel_migration/angel_migration.dart';
|
||||
import 'package:angel3_migration/angel3_migration.dart';
|
||||
import 'package:postgres/postgres.dart';
|
||||
import '../runner.dart';
|
||||
import '../util.dart';
|
||||
|
@ -9,7 +9,7 @@ import 'schema.dart';
|
|||
class PostgresMigrationRunner implements MigrationRunner {
|
||||
final Map<String, Migration> migrations = {};
|
||||
final PostgreSQLConnection connection;
|
||||
final Queue<Migration> _migrationQueue = new Queue();
|
||||
final Queue<Migration> _migrationQueue = Queue();
|
||||
bool _connected = false;
|
||||
|
||||
PostgresMigrationRunner(this.connection,
|
||||
|
@ -27,7 +27,7 @@ class PostgresMigrationRunner implements MigrationRunner {
|
|||
while (_migrationQueue.isNotEmpty) {
|
||||
var migration = _migrationQueue.removeFirst();
|
||||
var path = await absoluteSourcePath(migration.runtimeType);
|
||||
migrations.putIfAbsent(path.replaceAll("\\", "\\\\"), () => migration);
|
||||
migrations.putIfAbsent(path.replaceAll('\\', '\\\\'), () => migration);
|
||||
}
|
||||
|
||||
if (!_connected) {
|
||||
|
@ -49,8 +49,8 @@ class PostgresMigrationRunner implements MigrationRunner {
|
|||
Future up() async {
|
||||
await _init();
|
||||
var r = await connection.query('SELECT path from migrations;');
|
||||
Iterable<String> existing = r.expand((x) => x).cast<String>();
|
||||
List<String> toRun = [];
|
||||
var existing = r.expand((x) => x).cast<String>();
|
||||
var toRun = <String>[];
|
||||
|
||||
migrations.forEach((k, v) {
|
||||
if (!existing.contains(k)) toRun.add(k);
|
||||
|
@ -58,12 +58,12 @@ class PostgresMigrationRunner implements MigrationRunner {
|
|||
|
||||
if (toRun.isNotEmpty) {
|
||||
var r = await connection.query('SELECT MAX(batch) from migrations;');
|
||||
int curBatch = (r[0][0] ?? 0) as int;
|
||||
int batch = curBatch + 1;
|
||||
var curBatch = (r[0][0] ?? 0) as int;
|
||||
var batch = curBatch + 1;
|
||||
|
||||
for (var k in toRun) {
|
||||
var migration = migrations[k]!;
|
||||
var schema = new PostgresSchema();
|
||||
var schema = PostgresSchema();
|
||||
migration.up(schema);
|
||||
print('Bringing up "$k"...');
|
||||
await schema.run(connection).then((_) {
|
||||
|
@ -81,11 +81,11 @@ class PostgresMigrationRunner implements MigrationRunner {
|
|||
await _init();
|
||||
|
||||
var r = await connection.query('SELECT MAX(batch) from migrations;');
|
||||
int curBatch = (r[0][0] ?? 0) as int;
|
||||
var curBatch = (r[0][0] ?? 0) as int;
|
||||
r = await connection
|
||||
.query('SELECT path from migrations WHERE batch = $curBatch;');
|
||||
Iterable<String> existing = r.expand((x) => x).cast<String>();
|
||||
List<String> toRun = [];
|
||||
var existing = r.expand((x) => x).cast<String>();
|
||||
var toRun = <String>[];
|
||||
|
||||
migrations.forEach((k, v) {
|
||||
if (existing.contains(k)) toRun.add(k);
|
||||
|
@ -94,7 +94,7 @@ class PostgresMigrationRunner implements MigrationRunner {
|
|||
if (toRun.isNotEmpty) {
|
||||
for (var k in toRun.reversed) {
|
||||
var migration = migrations[k]!;
|
||||
var schema = new PostgresSchema();
|
||||
var schema = PostgresSchema();
|
||||
migration.down(schema);
|
||||
print('Bringing down "$k"...');
|
||||
await schema.run(connection).then((_) {
|
||||
|
@ -112,13 +112,13 @@ class PostgresMigrationRunner implements MigrationRunner {
|
|||
await _init();
|
||||
var r = await connection
|
||||
.query('SELECT path from migrations ORDER BY batch DESC;');
|
||||
Iterable<String> existing = r.expand((x) => x).cast<String>();
|
||||
var existing = r.expand((x) => x).cast<String>();
|
||||
var toRun = existing.where(migrations.containsKey).toList();
|
||||
|
||||
if (toRun.isNotEmpty) {
|
||||
for (var k in toRun.reversed) {
|
||||
var migration = migrations[k]!;
|
||||
var schema = new PostgresSchema();
|
||||
var schema = PostgresSchema();
|
||||
migration.down(schema);
|
||||
print('Bringing down "$k"...');
|
||||
await schema.run(connection).then((_) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'package:angel_migration/angel_migration.dart';
|
||||
import 'package:angel3_migration/angel3_migration.dart';
|
||||
import 'package:postgres/postgres.dart';
|
||||
import 'package:angel_migration_runner/src/postgres/table.dart';
|
||||
import 'package:angel3_migration_runner/src/postgres/table.dart';
|
||||
|
||||
class PostgresSchema extends Schema {
|
||||
final int _indent;
|
||||
|
@ -9,14 +9,14 @@ class PostgresSchema extends Schema {
|
|||
|
||||
PostgresSchema._(this._buf, this._indent);
|
||||
|
||||
factory PostgresSchema() => new PostgresSchema._(new StringBuffer(), 0);
|
||||
factory PostgresSchema() => PostgresSchema._(StringBuffer(), 0);
|
||||
|
||||
Future run(PostgreSQLConnection connection) => connection.execute(compile());
|
||||
|
||||
String compile() => _buf.toString();
|
||||
|
||||
void _writeln(String str) {
|
||||
for (int i = 0; i < _indent; i++) {
|
||||
for (var i = 0; i < _indent; i++) {
|
||||
_buf.write(' ');
|
||||
}
|
||||
|
||||
|
@ -24,23 +24,24 @@ class PostgresSchema extends Schema {
|
|||
}
|
||||
|
||||
@override
|
||||
void drop(String tableName, {bool cascade: false}) {
|
||||
void drop(String tableName, {bool cascade = false}) {
|
||||
var c = cascade == true ? ' CASCADE' : '';
|
||||
_writeln('DROP TABLE "$tableName"$c;');
|
||||
}
|
||||
|
||||
@override
|
||||
void alter(String tableName, void callback(MutableTable table)) {
|
||||
var tbl = new PostgresAlterTable(tableName);
|
||||
void alter(String tableName, void Function(MutableTable table) callback) {
|
||||
var tbl = PostgresAlterTable(tableName);
|
||||
callback(tbl);
|
||||
_writeln('ALTER TABLE "$tableName"');
|
||||
tbl.compile(_buf, _indent + 1);
|
||||
_buf.write(';');
|
||||
}
|
||||
|
||||
void _create(String tableName, void callback(Table table), bool ifNotExists) {
|
||||
void _create(
|
||||
String tableName, void Function(Table table) callback, bool ifNotExists) {
|
||||
var op = ifNotExists ? ' IF NOT EXISTS' : '';
|
||||
var tbl = new PostgresTable();
|
||||
var tbl = PostgresTable();
|
||||
callback(tbl);
|
||||
_writeln('CREATE TABLE$op "$tableName" (');
|
||||
tbl.compile(_buf, _indent + 1);
|
||||
|
@ -49,10 +50,11 @@ class PostgresSchema extends Schema {
|
|||
}
|
||||
|
||||
@override
|
||||
void create(String tableName, void callback(Table table)) =>
|
||||
void create(String tableName, void Function(Table table) callback) =>
|
||||
_create(tableName, callback, false);
|
||||
|
||||
@override
|
||||
void createIfNotExists(String tableName, void callback(Table table)) =>
|
||||
void createIfNotExists(
|
||||
String tableName, void Function(Table table) callback) =>
|
||||
_create(tableName, callback, true);
|
||||
}
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
import 'dart:collection';
|
||||
import 'package:angel_orm/angel_orm.dart';
|
||||
import 'package:angel_migration/angel_migration.dart';
|
||||
import 'package:angel3_orm/angel3_orm.dart';
|
||||
import 'package:angel3_migration/angel3_migration.dart';
|
||||
import 'package:charcode/ascii.dart';
|
||||
|
||||
abstract class PostgresGenerator {
|
||||
static String columnType(MigrationColumn column) {
|
||||
var str = column.type!.name;
|
||||
if (column.length != null)
|
||||
if (column.length != null) {
|
||||
return '$str(${column.length})';
|
||||
else
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
static String compileColumn(MigrationColumn column) {
|
||||
var buf = new StringBuffer(columnType(column));
|
||||
var buf = StringBuffer(columnType(column));
|
||||
|
||||
if (column.isNullable == false) buf.write(' NOT NULL');
|
||||
if (column.defaultValue != null) {
|
||||
String s;
|
||||
var value = column.defaultValue;
|
||||
if (value is RawSql)
|
||||
if (value is RawSql) {
|
||||
s = value.value;
|
||||
else if (value is String) {
|
||||
} else if (value is String) {
|
||||
var b = StringBuffer();
|
||||
for (var ch in value.codeUnits) {
|
||||
if (ch == $single_quote) {
|
||||
|
@ -38,10 +39,11 @@ abstract class PostgresGenerator {
|
|||
buf.write(' DEFAULT $s');
|
||||
}
|
||||
|
||||
if (column.indexType == IndexType.unique)
|
||||
if (column.indexType == IndexType.unique) {
|
||||
buf.write(' UNIQUE');
|
||||
else if (column.indexType == IndexType.primaryKey)
|
||||
} else if (column.indexType == IndexType.primaryKey) {
|
||||
buf.write(' PRIMARY KEY');
|
||||
}
|
||||
|
||||
for (var ref in column.externalReferences) {
|
||||
buf.write(' ' + compileReference(ref));
|
||||
|
@ -51,8 +53,8 @@ abstract class PostgresGenerator {
|
|||
}
|
||||
|
||||
static String compileReference(MigrationColumnReference ref) {
|
||||
var buf = new StringBuffer(
|
||||
'REFERENCES "${ref.foreignTable}"("${ref.foreignKey}")');
|
||||
var buf =
|
||||
StringBuffer('REFERENCES "${ref.foreignTable}"("${ref.foreignKey}")');
|
||||
if (ref.behavior != null) buf.write(' ' + ref.behavior!);
|
||||
return buf.toString();
|
||||
}
|
||||
|
@ -63,21 +65,22 @@ class PostgresTable extends Table {
|
|||
|
||||
@override
|
||||
MigrationColumn declareColumn(String name, Column column) {
|
||||
if (_columns.containsKey(name))
|
||||
throw new StateError('Cannot redeclare column "$name".');
|
||||
var col = new MigrationColumn.from(column);
|
||||
if (_columns.containsKey(name)) {
|
||||
throw StateError('Cannot redeclare column "$name".');
|
||||
}
|
||||
var col = MigrationColumn.from(column);
|
||||
_columns[name] = col;
|
||||
return col;
|
||||
}
|
||||
|
||||
void compile(StringBuffer buf, int indent) {
|
||||
int i = 0;
|
||||
var i = 0;
|
||||
|
||||
_columns.forEach((name, column) {
|
||||
var col = PostgresGenerator.compileColumn(column);
|
||||
if (i++ > 0) buf.writeln(',');
|
||||
|
||||
for (int i = 0; i < indent; i++) {
|
||||
for (var i = 0; i < indent; i++) {
|
||||
buf.write(' ');
|
||||
}
|
||||
|
||||
|
@ -89,19 +92,19 @@ class PostgresTable extends Table {
|
|||
class PostgresAlterTable extends Table implements MutableTable {
|
||||
final Map<String, MigrationColumn> _columns = {};
|
||||
final String tableName;
|
||||
final Queue<String> _stack = new Queue<String>();
|
||||
final Queue<String> _stack = Queue<String>();
|
||||
|
||||
PostgresAlterTable(this.tableName);
|
||||
|
||||
void compile(StringBuffer buf, int indent) {
|
||||
int i = 0;
|
||||
var i = 0;
|
||||
|
||||
while (_stack.isNotEmpty) {
|
||||
var str = _stack.removeFirst();
|
||||
|
||||
if (i++ > 0) buf.writeln(',');
|
||||
|
||||
for (int i = 0; i < indent; i++) {
|
||||
for (var i = 0; i < indent; i++) {
|
||||
buf.write(' ');
|
||||
}
|
||||
|
||||
|
@ -115,7 +118,7 @@ class PostgresAlterTable extends Table implements MutableTable {
|
|||
var col = PostgresGenerator.compileColumn(column);
|
||||
if (i++ > 0) buf.writeln(',');
|
||||
|
||||
for (int i = 0; i < indent; i++) {
|
||||
for (var i = 0; i < indent; i++) {
|
||||
buf.write(' ');
|
||||
}
|
||||
|
||||
|
@ -125,9 +128,10 @@ class PostgresAlterTable extends Table implements MutableTable {
|
|||
|
||||
@override
|
||||
MigrationColumn declareColumn(String name, Column column) {
|
||||
if (_columns.containsKey(name))
|
||||
throw new StateError('Cannot redeclare column "$name".');
|
||||
var col = new MigrationColumn.from(column);
|
||||
if (_columns.containsKey(name)) {
|
||||
throw StateError('Cannot redeclare column "$name".');
|
||||
}
|
||||
var col = MigrationColumn.from(column);
|
||||
_columns[name] = col;
|
||||
return col;
|
||||
}
|
||||
|
@ -145,8 +149,7 @@ class PostgresAlterTable extends Table implements MutableTable {
|
|||
@override
|
||||
void changeColumnType(String name, ColumnType type, {int? length}) {
|
||||
_stack.add('ALTER COLUMN "$name" TYPE ' +
|
||||
PostgresGenerator.columnType(
|
||||
new MigrationColumn(type, length: length)));
|
||||
PostgresGenerator.columnType(MigrationColumn(type, length: length)));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'package:angel_migration/angel_migration.dart';
|
||||
import 'package:angel3_migration/angel3_migration.dart';
|
||||
|
||||
abstract class MigrationRunner {
|
||||
void addMigration(Migration migration);
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
name: angel3_migration_runner
|
||||
version: 4.0.0-beta.1
|
||||
description: Command-line based database migration runner for Angel's ORM.
|
||||
homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/orm/angel3_migration_runner
|
||||
homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/orm/angel_migration_runner
|
||||
environment:
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
dependencies:
|
||||
angel3_migration: ^4.0.0-beta.1
|
||||
angel3_orm: ^4.0.0
|
||||
angel3_orm: ^4.0.0-beta.1
|
||||
args: ^2.1.0
|
||||
charcode: ^1.2.0
|
||||
postgres: ^2.3.2
|
||||
pedantic: ^1.11.0
|
||||
|
|
Loading…
Reference in a new issue