mirror of https://github.com/AMT-Cheif/drift.git
Add tests for schema verification, fix inconsistencies
This commit is contained in:
parent
10620cf738
commit
7e88e74a6c
|
@ -40,10 +40,9 @@ class CreateTableReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
final foundColumns = <String, MoorColumn>{};
|
final foundColumns = <String, MoorColumn>{};
|
||||||
final primaryKey = <MoorColumn>{};
|
Set<MoorColumn> primaryKeyFromTableConstraint;
|
||||||
|
|
||||||
for (final column in table.resultColumns) {
|
for (final column in table.resultColumns) {
|
||||||
var isPrimaryKey = false;
|
|
||||||
final features = <ColumnFeature>[];
|
final features = <ColumnFeature>[];
|
||||||
final sqlName = column.name;
|
final sqlName = column.name;
|
||||||
final dartName = ReCase(sqlName).camelCase;
|
final dartName = ReCase(sqlName).camelCase;
|
||||||
|
@ -87,7 +86,6 @@ class CreateTableReader {
|
||||||
: const Iterable<ColumnConstraint>.empty();
|
: const Iterable<ColumnConstraint>.empty();
|
||||||
for (final constraint in constraints) {
|
for (final constraint in constraints) {
|
||||||
if (constraint is PrimaryKeyColumn) {
|
if (constraint is PrimaryKeyColumn) {
|
||||||
isPrimaryKey = true;
|
|
||||||
features.add(const PrimaryKey());
|
features.add(const PrimaryKey());
|
||||||
if (constraint.autoIncrement) {
|
if (constraint.autoIncrement) {
|
||||||
features.add(AutoIncrement());
|
features.add(AutoIncrement());
|
||||||
|
@ -153,9 +151,6 @@ class CreateTableReader {
|
||||||
);
|
);
|
||||||
|
|
||||||
foundColumns[column.name] = parsed;
|
foundColumns[column.name] = parsed;
|
||||||
if (isPrimaryKey) {
|
|
||||||
primaryKey.add(parsed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final tableName = table.name;
|
final tableName = table.name;
|
||||||
|
@ -167,9 +162,11 @@ class CreateTableReader {
|
||||||
|
|
||||||
for (final keyConstraint in table.tableConstraints.whereType<KeyClause>()) {
|
for (final keyConstraint in table.tableConstraints.whereType<KeyClause>()) {
|
||||||
if (keyConstraint.isPrimaryKey) {
|
if (keyConstraint.isPrimaryKey) {
|
||||||
primaryKey.addAll(keyConstraint.indexedColumns
|
primaryKeyFromTableConstraint = {
|
||||||
.map((r) => foundColumns[r.columnName])
|
for (final column in keyConstraint.indexedColumns)
|
||||||
.where((c) => c != null));
|
if (foundColumns.containsKey(column.columnName))
|
||||||
|
foundColumns[column.columnName]
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +176,7 @@ class CreateTableReader {
|
||||||
sqlName: table.name,
|
sqlName: table.name,
|
||||||
dartTypeName: dataClassName,
|
dartTypeName: dataClassName,
|
||||||
overriddenName: dartTableName,
|
overriddenName: dartTableName,
|
||||||
primaryKey: primaryKey,
|
primaryKey: primaryKeyFromTableConstraint,
|
||||||
overrideWithoutRowId: table.withoutRowId ? true : null,
|
overrideWithoutRowId: table.withoutRowId ? true : null,
|
||||||
overrideTableConstraints: constraints.isNotEmpty ? constraints : null,
|
overrideTableConstraints: constraints.isNotEmpty ? constraints : null,
|
||||||
// we take care of writing the primary key ourselves
|
// we take care of writing the primary key ourselves
|
||||||
|
|
|
@ -8,6 +8,9 @@ abstract class TableDeclaration extends Declaration {
|
||||||
abstract class TableDeclarationWithSql implements TableDeclaration {
|
abstract class TableDeclarationWithSql implements TableDeclaration {
|
||||||
/// The `CREATE TABLE` statement used to create this table.
|
/// The `CREATE TABLE` statement used to create this table.
|
||||||
String get createSql;
|
String get createSql;
|
||||||
|
|
||||||
|
/// The parsed statement creating this table.
|
||||||
|
TableInducingStatement get creatingStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DartTableDeclaration implements TableDeclaration, DartDeclaration {
|
class DartTableDeclaration implements TableDeclaration, DartDeclaration {
|
||||||
|
@ -38,12 +41,6 @@ class MoorTableDeclaration
|
||||||
@override
|
@override
|
||||||
final TableInducingStatement node;
|
final TableInducingStatement node;
|
||||||
|
|
||||||
@override
|
|
||||||
bool get isVirtual => node is CreateVirtualTableStatement;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get createSql => node.span.text;
|
|
||||||
|
|
||||||
MoorTableDeclaration._(this.declaration, this.node);
|
MoorTableDeclaration._(this.declaration, this.node);
|
||||||
|
|
||||||
factory MoorTableDeclaration(TableInducingStatement node, FoundFile file) {
|
factory MoorTableDeclaration(TableInducingStatement node, FoundFile file) {
|
||||||
|
@ -52,13 +49,22 @@ class MoorTableDeclaration
|
||||||
node,
|
node,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isVirtual => node is CreateVirtualTableStatement;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get createSql => node.span.text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
TableInducingStatement get creatingStatement => node;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomVirtualTableDeclaration implements TableDeclarationWithSql {
|
class CustomVirtualTableDeclaration implements TableDeclarationWithSql {
|
||||||
@override
|
@override
|
||||||
final String createSql;
|
final CreateVirtualTableStatement creatingStatement;
|
||||||
|
|
||||||
CustomVirtualTableDeclaration(this.createSql);
|
CustomVirtualTableDeclaration(this.creatingStatement);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
SourceRange get declaration {
|
SourceRange get declaration {
|
||||||
|
@ -67,6 +73,9 @@ class CustomVirtualTableDeclaration implements TableDeclarationWithSql {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get isVirtual => true;
|
bool get isVirtual => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get createSql => creatingStatement.span.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomTableDeclaration implements TableDeclaration {
|
class CustomTableDeclaration implements TableDeclaration {
|
||||||
|
|
|
@ -114,8 +114,7 @@ class MoorTable implements MoorSchemaEntity {
|
||||||
String get createVirtual {
|
String get createVirtual {
|
||||||
if (!isVirtualTable) return null;
|
if (!isVirtualTable) return null;
|
||||||
|
|
||||||
final node = (declaration as MoorTableDeclaration).node;
|
return (declaration as TableDeclarationWithSql).createSql;
|
||||||
return (node as CreateVirtualTableStatement).span.text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MoorTable({
|
MoorTable({
|
||||||
|
|
|
@ -111,6 +111,22 @@ class FindSchemaDifferences {
|
||||||
CreateTableStatement ref, CreateTableStatement act) {
|
CreateTableStatement ref, CreateTableStatement act) {
|
||||||
final results = <String, CompareResult>{};
|
final results = <String, CompareResult>{};
|
||||||
|
|
||||||
|
results['columns'] = _compareColumns(ref.columns, act.columns);
|
||||||
|
|
||||||
|
// We're currently comparing table constraints by their exact order.
|
||||||
|
if (ref.tableConstraints.length != act.tableConstraints.length) {
|
||||||
|
results['constraints'] = FoundDifference(
|
||||||
|
'Expected the table to have ${ref.tableConstraints.length} table '
|
||||||
|
'constraints, it actually has ${act.tableConstraints.length}.');
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < ref.tableConstraints.length; i++) {
|
||||||
|
final refConstraint = ref.tableConstraints[i];
|
||||||
|
final actConstraint = act.tableConstraints[i];
|
||||||
|
|
||||||
|
results['constraints_$i'] = _compareByAst(refConstraint, actConstraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ref.withoutRowId != act.withoutRowId) {
|
if (ref.withoutRowId != act.withoutRowId) {
|
||||||
final expectedWithout = ref.withoutRowId;
|
final expectedWithout = ref.withoutRowId;
|
||||||
results['rowid'] = FoundDifference(expectedWithout
|
results['rowid'] = FoundDifference(expectedWithout
|
||||||
|
@ -118,7 +134,35 @@ class FindSchemaDifferences {
|
||||||
: 'Did not expect the table to have a WITHOUT ROWID clause.');
|
: 'Did not expect the table to have a WITHOUT ROWID clause.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return const Success();
|
return MultiResult(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompareResult _compareColumns(
|
||||||
|
List<ColumnDefinition> ref, List<ColumnDefinition> act) {
|
||||||
|
final results = <String, CompareResult>{};
|
||||||
|
|
||||||
|
final actByName = {for (final column in act) column.columnName: column};
|
||||||
|
// Additional columns in act that ref doesn't have. Built by iterating over
|
||||||
|
// ref.
|
||||||
|
final additionalColumns = actByName.keys.toSet();
|
||||||
|
|
||||||
|
for (final refColumn in ref) {
|
||||||
|
final name = refColumn.columnName;
|
||||||
|
final actColumn = actByName[name];
|
||||||
|
|
||||||
|
if (actColumn == null) {
|
||||||
|
results[name] = FoundDifference('Missing in schema');
|
||||||
|
} else {
|
||||||
|
results[name] = _compareByAst(refColumn, actColumn);
|
||||||
|
additionalColumns.remove(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final additional in additionalColumns) {
|
||||||
|
results[additional] = FoundDifference('Additional unexpected column');
|
||||||
|
}
|
||||||
|
|
||||||
|
return MultiResult(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult _compareByAst(AstNode a, AstNode b) {
|
CompareResult _compareByAst(AstNode a, AstNode b) {
|
||||||
|
@ -153,7 +197,8 @@ abstract class CompareResult {
|
||||||
|
|
||||||
bool get noChanges;
|
bool get noChanges;
|
||||||
|
|
||||||
String describe(int indent);
|
String describe() => _describe(0);
|
||||||
|
String _describe(int indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Success extends CompareResult {
|
class Success extends CompareResult {
|
||||||
|
@ -163,7 +208,7 @@ class Success extends CompareResult {
|
||||||
bool get noChanges => true;
|
bool get noChanges => true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String describe(int indent) => '${' ' * indent}matches schema ✓';
|
String _describe(int indent) => '${' ' * indent}matches schema ✓';
|
||||||
}
|
}
|
||||||
|
|
||||||
class FoundDifference extends CompareResult {
|
class FoundDifference extends CompareResult {
|
||||||
|
@ -175,7 +220,7 @@ class FoundDifference extends CompareResult {
|
||||||
bool get noChanges => false;
|
bool get noChanges => false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String describe(int indent) => ' ' * indent + description;
|
String _describe(int indent) => ' ' * indent + description;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiResult extends CompareResult {
|
class MultiResult extends CompareResult {
|
||||||
|
@ -187,14 +232,16 @@ class MultiResult extends CompareResult {
|
||||||
bool get noChanges => nestedResults.values.every((e) => e.noChanges);
|
bool get noChanges => nestedResults.values.every((e) => e.noChanges);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String describe(int indent) {
|
String _describe(int indent) {
|
||||||
final buffer = StringBuffer();
|
final buffer = StringBuffer();
|
||||||
final indentStr = ' ' * indent;
|
final indentStr = ' ' * indent;
|
||||||
|
|
||||||
for (final result in nestedResults.entries) {
|
for (final result in nestedResults.entries) {
|
||||||
|
if (result.value.noChanges) continue;
|
||||||
|
|
||||||
buffer
|
buffer
|
||||||
..writeln('$indentStr${result.key}:')
|
..writeln('$indentStr${result.key}:')
|
||||||
..writeln(result.value.describe(indent + 1));
|
..writeln(result.value._describe(indent + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:moor_generator/moor_generator.dart';
|
import 'package:moor_generator/moor_generator.dart';
|
||||||
import 'package:recase/recase.dart';
|
import 'package:recase/recase.dart';
|
||||||
|
import 'package:sqlparser/sqlparser.dart';
|
||||||
|
|
||||||
const _infoVersion = '0.1.0-dev-preview';
|
const _infoVersion = '0.1.0-dev-preview';
|
||||||
|
|
||||||
|
@ -129,6 +130,8 @@ class SchemaReader {
|
||||||
|
|
||||||
final Set<int> _currentlyProcessing = {};
|
final Set<int> _currentlyProcessing = {};
|
||||||
|
|
||||||
|
final SqlEngine _engine = SqlEngine();
|
||||||
|
|
||||||
SchemaReader._();
|
SchemaReader._();
|
||||||
|
|
||||||
factory SchemaReader.readJson(Map<String, dynamic> json) {
|
factory SchemaReader.readJson(Map<String, dynamic> json) {
|
||||||
|
@ -221,11 +224,13 @@ class SchemaReader {
|
||||||
|
|
||||||
if (isVirtual) {
|
if (isVirtual) {
|
||||||
final create = content['create_virtual_stmt'] as String;
|
final create = content['create_virtual_stmt'] as String;
|
||||||
|
final parsed =
|
||||||
|
_engine.parse(create).rootNode as CreateVirtualTableStatement;
|
||||||
|
|
||||||
return MoorTable(
|
return MoorTable(
|
||||||
sqlName: sqlName,
|
sqlName: sqlName,
|
||||||
overriddenName: sqlName,
|
overriddenName: sqlName,
|
||||||
declaration: CustomVirtualTableDeclaration(create),
|
declaration: CustomVirtualTableDeclaration(parsed),
|
||||||
overrideWithoutRowId: withoutRowId,
|
overrideWithoutRowId: withoutRowId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -244,7 +249,7 @@ class SchemaReader {
|
||||||
if (content.containsKey('explicit_pk')) {
|
if (content.containsKey('explicit_pk')) {
|
||||||
explicitPk = {
|
explicitPk = {
|
||||||
for (final columnName in content['explicit_pk'] as List<dynamic>)
|
for (final columnName in content['explicit_pk'] as List<dynamic>)
|
||||||
columns.singleWhere((c) => c.name == columnName)
|
columns.singleWhere((c) => c.name.name == columnName)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class VerifierImplementation implements SchemaVerifier {
|
||||||
.compare();
|
.compare();
|
||||||
|
|
||||||
if (!result.noChanges) {
|
if (!result.noChanges) {
|
||||||
throw SchemaMismatch(result.describe(0));
|
throw SchemaMismatch(result.describe());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -246,7 +246,7 @@ class TableWriter {
|
||||||
|
|
||||||
void _writePrimaryKeyOverride() {
|
void _writePrimaryKeyOverride() {
|
||||||
_buffer.write('@override\nSet<GeneratedColumn> get \$primaryKey => ');
|
_buffer.write('@override\nSet<GeneratedColumn> get \$primaryKey => ');
|
||||||
var primaryKey = table.primaryKey;
|
var primaryKey = table.fullPrimaryKey;
|
||||||
|
|
||||||
// If there is an auto increment column, that forms the primary key. The
|
// If there is an auto increment column, that forms the primary key. The
|
||||||
// PK returned by table.primaryKey only contains column that have been
|
// PK returned by table.primaryKey only contains column that have been
|
||||||
|
@ -306,8 +306,8 @@ class TableWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table.isVirtualTable) {
|
if (table.isVirtualTable) {
|
||||||
final declaration = table.declaration as MoorTableDeclaration;
|
final declaration = table.declaration as TableDeclarationWithSql;
|
||||||
final stmt = declaration.node as CreateVirtualTableStatement;
|
final stmt = declaration.creatingStatement as CreateVirtualTableStatement;
|
||||||
final moduleAndArgs = asDartLiteral(
|
final moduleAndArgs = asDartLiteral(
|
||||||
'${stmt.moduleName}(${stmt.argumentContent.join(', ')})');
|
'${stmt.moduleName}(${stmt.argumentContent.join(', ')})');
|
||||||
_buffer
|
_buffer
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
import 'package:moor_generator/src/services/schema/find_differences.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('compares individual', () {
|
||||||
|
group('tables', () {
|
||||||
|
test('with rowid mismatch', () {
|
||||||
|
final result = compare(
|
||||||
|
Input('a', 'CREATE TABLE a (id INTEGER) WITHOUT ROWID;'),
|
||||||
|
Input('a', 'CREATE TABLE a (id INTEGER);'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result, hasChanges);
|
||||||
|
expect(
|
||||||
|
result.describe(),
|
||||||
|
contains('Expected the table to have a WITHOUT ROWID clause'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with too few columns', () {
|
||||||
|
final result = compare(
|
||||||
|
Input('a', 'CREATE TABLE a (id INTEGER, b TEXT);'),
|
||||||
|
Input('a', 'CREATE TABLE a (id INTEGER);'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result, hasChanges);
|
||||||
|
expect(
|
||||||
|
result.describe(),
|
||||||
|
contains('Missing in schema'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with too many columns', () {
|
||||||
|
final result = compare(
|
||||||
|
Input('a', 'CREATE TABLE a (id INTEGER);'),
|
||||||
|
Input('a', 'CREATE TABLE a (id INTEGER, b TEXT);'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result, hasChanges);
|
||||||
|
expect(
|
||||||
|
result.describe(),
|
||||||
|
contains('Additional unexpected column'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('that are equal', () {
|
||||||
|
final result = compare(
|
||||||
|
Input('a', 'CREATE TABLE a (b TEXT, id INTEGER PRIMARY KEY);'),
|
||||||
|
Input('a', 'CREATE TABLE a (id INTEGER PRIMARY KEY, b TEXT);'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result, hasNoChanges);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('of different type', () {
|
||||||
|
final result = compare(
|
||||||
|
Input('a', 'CREATE TABLE a (id INTEGER);'),
|
||||||
|
Input('a', 'CREATE INDEX a ON b (c, d);'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result, hasChanges);
|
||||||
|
expect(
|
||||||
|
result.describe(),
|
||||||
|
contains('Expected a table, but got a index.'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CompareResult compare(Input a, Input b) {
|
||||||
|
return FindSchemaDifferences([a], [b], false).compare();
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher hasChanges = _matchChanges(false);
|
||||||
|
Matcher hasNoChanges = _matchChanges(true);
|
||||||
|
|
||||||
|
Matcher _matchChanges(bool expectNoChanges) {
|
||||||
|
return isA<CompareResult>()
|
||||||
|
.having((e) => e.noChanges, 'noChanges', expectNoChanges);
|
||||||
|
}
|
|
@ -1,8 +1,12 @@
|
||||||
@Tags(['analyzer'])
|
@Tags(['analyzer'])
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:moor_generator/moor_generator.dart';
|
||||||
|
import 'package:moor_generator/src/analyzer/options.dart';
|
||||||
import 'package:moor_generator/src/analyzer/runner/results.dart';
|
import 'package:moor_generator/src/analyzer/runner/results.dart';
|
||||||
import 'package:moor_generator/src/services/schema/schema_files.dart';
|
import 'package:moor_generator/src/services/schema/schema_files.dart';
|
||||||
|
import 'package:moor_generator/src/writer/database_writer.dart';
|
||||||
|
import 'package:moor_generator/src/writer/writer.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
import '../../analyzer/utils.dart';
|
import '../../analyzer/utils.dart';
|
||||||
|
@ -20,6 +24,8 @@ CREATE TABLE "groups" (
|
||||||
UNIQUE(name)
|
UNIQUE(name)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE VIRTUAL TABLE email USING fts5(sender, title, body);
|
||||||
|
|
||||||
CREATE TABLE group_members (
|
CREATE TABLE group_members (
|
||||||
"group" INT NOT NULL REFERENCES "groups"(id),
|
"group" INT NOT NULL REFERENCES "groups"(id),
|
||||||
user INT NOT NULL REFERENCES users(id),
|
user INT NOT NULL REFERENCES users(id),
|
||||||
|
@ -56,7 +62,7 @@ class SettingsConverter extends TypeConverter<Settings, String> {
|
||||||
@UseMoor(include: {'a.moor'}, tables: [Users])
|
@UseMoor(include: {'a.moor'}, tables: [Users])
|
||||||
class Database {}
|
class Database {}
|
||||||
''',
|
''',
|
||||||
});
|
}, options: const MoorOptions(modules: [SqlModule.fts5]));
|
||||||
|
|
||||||
final file = await state.analyze('package:foo/main.dart');
|
final file = await state.analyze('package:foo/main.dart');
|
||||||
expect(state.session.errorsInFileAndImports(file), isEmpty);
|
expect(state.session.errorsInFileAndImports(file), isEmpty);
|
||||||
|
@ -67,6 +73,18 @@ class Database {}
|
||||||
final schemaJson = SchemaWriter(db).createSchemaJson();
|
final schemaJson = SchemaWriter(db).createSchemaJson();
|
||||||
expect(schemaJson, json.decode(expected));
|
expect(schemaJson, json.decode(expected));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('can generate code from schema json', () {
|
||||||
|
final reader =
|
||||||
|
SchemaReader.readJson(json.decode(expected) as Map<String, dynamic>);
|
||||||
|
final fakeDb = Database()..entities = [...reader.entities];
|
||||||
|
|
||||||
|
// Write the database. Not crashing is good enough for us here, we have
|
||||||
|
// separate tests for verification
|
||||||
|
final writer = Writer(const MoorOptions(),
|
||||||
|
generationOptions: const GenerationOptions(forSchema: 1));
|
||||||
|
DatabaseWriter(fakeDb, writer.child()).write();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const expected = r'''
|
const expected = r'''
|
||||||
|
@ -78,9 +96,7 @@ const expected = r'''
|
||||||
"entities":[
|
"entities":[
|
||||||
{
|
{
|
||||||
"id":0,
|
"id":0,
|
||||||
"references":[
|
"references":[],
|
||||||
|
|
||||||
],
|
|
||||||
"type":"table",
|
"type":"table",
|
||||||
"data":{
|
"data":{
|
||||||
"name":"groups",
|
"name":"groups",
|
||||||
|
@ -113,17 +129,12 @@ const expected = r'''
|
||||||
"is_virtual":false,
|
"is_virtual":false,
|
||||||
"constraints":[
|
"constraints":[
|
||||||
"UNIQUE(name)"
|
"UNIQUE(name)"
|
||||||
],
|
|
||||||
"explicit_pk":[
|
|
||||||
"id"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id":1,
|
"id":1,
|
||||||
"references":[
|
"references":[],
|
||||||
|
|
||||||
],
|
|
||||||
"type":"table",
|
"type":"table",
|
||||||
"data":{
|
"data":{
|
||||||
"name":"users",
|
"name":"users",
|
||||||
|
@ -254,6 +265,46 @@ const expected = r'''
|
||||||
"name":"groups_name",
|
"name":"groups_name",
|
||||||
"sql":"CREATE INDEX groups_name ON \"groups\"(name);"
|
"sql":"CREATE INDEX groups_name ON \"groups\"(name);"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"references": [],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "email",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "sender",
|
||||||
|
"moor_type": "ColumnType.text",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "title",
|
||||||
|
"moor_type": "ColumnType.text",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body",
|
||||||
|
"moor_type": "ColumnType.text",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": true,
|
||||||
|
"create_virtual_stmt": "CREATE VIRTUAL TABLE email USING fts5(sender, title, body);"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue