Support drift-defined views schema tools (#1813)

This commit is contained in:
Simon Binder 2022-04-23 23:31:04 +02:00
parent d0694f9d65
commit 80c8c86031
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
17 changed files with 398 additions and 41 deletions

View File

@ -60,6 +60,22 @@ class SchemaWriter {
'name': entity.name,
'sql': entity.createStmt,
};
} else if (entity is MoorView) {
if (entity.declaration is! MoorViewDeclaration) {
throw UnsupportedError(
'Exporting Dart-defined views into a schema is not '
'currently supported');
}
type = 'view';
data = {
'name': entity.name,
'sql': entity
.createSql(const MoorOptions.defaults(newSqlCodeGeneration: true)),
'dart_data_name': entity.dartTypeName,
'dart_info_name': entity.entityInfoName,
'columns': [for (final column in entity.columns) _columnData(column)],
};
} else if (entity is SpecialQuery) {
type = 'special-query';
data = {
@ -200,6 +216,9 @@ class SchemaReader {
case 'table':
entity = _readTable(content);
break;
case 'view':
entity = _readView(content);
break;
case 'special-query':
// Not relevant for the schema.
return;
@ -284,6 +303,18 @@ class SchemaReader {
);
}
MoorView _readView(Map<String, dynamic> content) {
return MoorView(
declaration: null,
name: content['name'] as String,
dartTypeName: content['dart_data_name'] as String,
entityInfoName: content['dart_info_name'] as String,
)..columns = [
for (final column in content['columns'])
_readColumn(column as Map<String, dynamic>)
];
}
MoorColumn _readColumn(Map<String, dynamic> data) {
final name = data['name'] as String;
final moorType = ColumnType.values

View File

@ -40,6 +40,8 @@ CREATE TRIGGER delete_empty_groups AFTER DELETE ON group_members BEGIN
END;
CREATE INDEX groups_name ON "groups"(name);
CREATE VIEW my_view AS SELECT id FROM "groups";
''',
'foo|lib/main.dart': '''
import 'package:drift/drift.dart';
@ -281,6 +283,33 @@ const expected = r'''
},
{
"id": 5,
"references": [
0
],
"type": "view",
"data": {
"name": "my_view",
"sql": "CREATE VIEW my_view AS SELECT id FROM \"groups\"",
"dart_data_name": "MyViewData",
"dart_info_name": "MyView",
"columns": [
{
"name": "id",
"getter_name": "id",
"moor_type": "ColumnType.integer",
"nullable": false,
"customConstraints": null,
"default_dart": null,
"default_client_dart": null,
"dsl_features": [
]
}
]
}
},
{
"id": 6,
"references": [
],

View File

@ -1 +1 @@
{"_meta":{"description":"This file contains a serialized version of schema entities for moor.","version":"0.1.0-dev-preview"},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"users","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"ColumnType.integer","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment","primary-key"]},{"name":"name","getter_name":"name","moor_type":"ColumnType.text","nullable":false,"customConstraints":null,"default_dart":"const Constant('name')","default_client_dart":null,"dsl_features":[]},{"name":"next_user","getter_name":"nextUser","moor_type":"ColumnType.integer","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES users (id)","default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false}},{"id":1,"references":[0],"type":"table","data":{"name":"groups","was_declared_in_moor":true,"columns":[{"name":"id","getter_name":"id","moor_type":"ColumnType.integer","nullable":false,"customConstraints":"NOT NULL","default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"title","getter_name":"title","moor_type":"ColumnType.text","nullable":false,"customConstraints":"NOT NULL","default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"deleted","getter_name":"deleted","moor_type":"ColumnType.boolean","nullable":true,"customConstraints":"DEFAULT FALSE","default_dart":"const CustomExpression<bool>('FALSE')","default_client_dart":null,"dsl_features":[]},{"name":"owner","getter_name":"owner","moor_type":"ColumnType.integer","nullable":false,"customConstraints":"NOT NULL REFERENCES users (id)","default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"constraints":["PRIMARY KEY (id)"],"explicit_pk":["id"]}}]}
{"_meta":{"description":"This file contains a serialized version of schema entities for moor.","version":"0.1.0-dev-preview"},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"users","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"ColumnType.integer","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment","primary-key"]},{"name":"name","getter_name":"name","moor_type":"ColumnType.text","nullable":false,"customConstraints":null,"default_dart":"const Constant('name')","default_client_dart":null,"dsl_features":[]},{"name":"next_user","getter_name":"nextUser","moor_type":"ColumnType.integer","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES users (id)","default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false}},{"id":1,"references":[0],"type":"table","data":{"name":"groups","was_declared_in_moor":true,"columns":[{"name":"id","getter_name":"id","moor_type":"ColumnType.integer","nullable":false,"customConstraints":"NOT NULL","default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"title","getter_name":"title","moor_type":"ColumnType.text","nullable":false,"customConstraints":"NOT NULL","default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"deleted","getter_name":"deleted","moor_type":"ColumnType.boolean","nullable":true,"customConstraints":"DEFAULT FALSE","default_dart":"const CustomExpression<bool>('FALSE')","default_client_dart":null,"dsl_features":[]},{"name":"owner","getter_name":"owner","moor_type":"ColumnType.integer","nullable":false,"customConstraints":"NOT NULL REFERENCES users (id)","default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"constraints":["PRIMARY KEY (id)"],"explicit_pk":["id"]}},{"id":2,"references":[1,0],"type":"view","data":{"name":"group_count","sql":"CREATE VIEW group_count AS SELECT users.*, (SELECT COUNT(*) FROM \"groups\" WHERE owner = users.id) AS group_count FROM users","dart_data_name":"GroupCountData","dart_info_name":"GroupCount","columns":[{"name":"id","getter_name":"id","moor_type":"ColumnType.integer","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"ColumnType.text","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"next_user","getter_name":"nextUser","moor_type":"ColumnType.integer","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"group_count","getter_name":"groupCount","moor_type":"ColumnType.integer","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}]}}]}

View File

@ -44,6 +44,9 @@ class Database extends _$Database {
} else if (target == 5) {
// Just add a new column that was added in version 5;
await m.addColumn(users, users.nextUser);
// And create the view on users
await m.createView(groupCount);
}
}
},

View File

@ -204,8 +204,6 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
User map(Map<String, dynamic> data, {String? tablePrefix}) {
return User.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);
@ -454,8 +452,6 @@ class Groups extends Table with TableInfo<Groups, Group> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
Group map(Map<String, dynamic> data, {String? tablePrefix}) {
return Group.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);
@ -472,13 +468,135 @@ class Groups extends Table with TableInfo<Groups, Group> {
bool get dontWriteConstraints => true;
}
class GroupCountData extends DataClass {
final int id;
final String name;
final int? nextUser;
final int groupCount;
GroupCountData(
{required this.id,
required this.name,
this.nextUser,
required this.groupCount});
factory GroupCountData.fromData(Map<String, dynamic> data, {String? prefix}) {
final effectivePrefix = prefix ?? '';
return GroupCountData(
id: const IntType()
.mapFromDatabaseResponse(data['${effectivePrefix}id'])!,
name: const StringType()
.mapFromDatabaseResponse(data['${effectivePrefix}name'])!,
nextUser: const IntType()
.mapFromDatabaseResponse(data['${effectivePrefix}next_user']),
groupCount: const IntType()
.mapFromDatabaseResponse(data['${effectivePrefix}group_count'])!,
);
}
factory GroupCountData.fromJson(Map<String, dynamic> json,
{ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return GroupCountData(
id: serializer.fromJson<int>(json['id']),
name: serializer.fromJson<String>(json['name']),
nextUser: serializer.fromJson<int?>(json['nextUser']),
groupCount: serializer.fromJson<int>(json['groupCount']),
);
}
@override
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'name': serializer.toJson<String>(name),
'nextUser': serializer.toJson<int?>(nextUser),
'groupCount': serializer.toJson<int>(groupCount),
};
}
GroupCountData copyWith(
{int? id, String? name, int? nextUser, int? groupCount}) =>
GroupCountData(
id: id ?? this.id,
name: name ?? this.name,
nextUser: nextUser ?? this.nextUser,
groupCount: groupCount ?? this.groupCount,
);
@override
String toString() {
return (StringBuffer('GroupCountData(')
..write('id: $id, ')
..write('name: $name, ')
..write('nextUser: $nextUser, ')
..write('groupCount: $groupCount')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, name, nextUser, groupCount);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is GroupCountData &&
other.id == this.id &&
other.name == this.name &&
other.nextUser == this.nextUser &&
other.groupCount == this.groupCount);
}
class GroupCount extends ViewInfo<GroupCount, GroupCountData>
implements HasResultSet {
final String? _alias;
@override
final _$Database attachedDatabase;
GroupCount(this.attachedDatabase, [this._alias]);
@override
List<GeneratedColumn> get $columns => [id, name, nextUser, groupCount];
@override
String get aliasedName => _alias ?? entityName;
@override
String get entityName => 'group_count';
@override
String get createViewStmt =>
'CREATE VIEW group_count AS SELECT\n users.*,\n (SELECT COUNT(*) FROM "groups" WHERE owner = users.id) AS group_count\n FROM users;';
@override
GroupCount get asDslTable => this;
@override
GroupCountData map(Map<String, dynamic> data, {String? tablePrefix}) {
return GroupCountData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);
}
late final GeneratedColumn<int?> id =
GeneratedColumn<int?>('id', aliasedName, false, type: const IntType());
late final GeneratedColumn<String?> name = GeneratedColumn<String?>(
'name', aliasedName, false,
type: const StringType());
late final GeneratedColumn<int?> nextUser = GeneratedColumn<int?>(
'next_user', aliasedName, true,
type: const IntType());
late final GeneratedColumn<int?> groupCount = GeneratedColumn<int?>(
'group_count', aliasedName, false,
type: const IntType());
@override
GroupCount createAlias(String alias) {
return GroupCount(attachedDatabase, alias);
}
@override
Query? get query => null;
@override
Set<String> get readTables => const {'groups', 'users'};
}
abstract class _$Database extends GeneratedDatabase {
_$Database(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
_$Database.connect(DatabaseConnection c) : super.connect(c);
late final $UsersTable users = $UsersTable(this);
late final Groups groups = Groups(this);
late final GroupCount groupCount = GroupCount(this);
@override
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
@override
List<DatabaseSchemaEntity> get allSchemaEntities => [users, groups];
List<DatabaseSchemaEntity> get allSchemaEntities =>
[users, groups, groupCount];
}

View File

@ -21,8 +21,6 @@ class Users extends Table with TableInfo {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
throw UnsupportedError('TableInfo.map in schema verification code');
}

View File

@ -24,8 +24,6 @@ class Users extends Table with TableInfo {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
throw UnsupportedError('TableInfo.map in schema verification code');
}

View File

@ -24,8 +24,6 @@ class Users extends Table with TableInfo {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
throw UnsupportedError('TableInfo.map in schema verification code');
}
@ -74,8 +72,6 @@ class Groups extends Table with TableInfo {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
throw UnsupportedError('TableInfo.map in schema verification code');
}

View File

@ -26,8 +26,6 @@ class Users extends Table with TableInfo {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
throw UnsupportedError('TableInfo.map in schema verification code');
}
@ -76,8 +74,6 @@ class Groups extends Table with TableInfo {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
throw UnsupportedError('TableInfo.map in schema verification code');
}

View File

@ -31,8 +31,6 @@ class Users extends Table with TableInfo {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
throw UnsupportedError('TableInfo.map in schema verification code');
}
@ -81,8 +79,6 @@ class Groups extends Table with TableInfo {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
throw UnsupportedError('TableInfo.map in schema verification code');
}
@ -98,15 +94,59 @@ class Groups extends Table with TableInfo {
bool get dontWriteConstraints => true;
}
class GroupCount extends ViewInfo<GroupCount, Never> implements HasResultSet {
final String? _alias;
@override
final DatabaseAtV5 attachedDatabase;
GroupCount(this.attachedDatabase, [this._alias]);
@override
List<GeneratedColumn> get $columns => [id, name, nextUser, groupCount];
@override
String get aliasedName => _alias ?? entityName;
@override
String get entityName => 'group_count';
@override
String? get createViewStmt => null;
@override
GroupCount get asDslTable => this;
@override
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
throw UnsupportedError('TableInfo.map in schema verification code');
}
late final GeneratedColumn<int?> id =
GeneratedColumn<int?>('id', aliasedName, false, type: const IntType());
late final GeneratedColumn<String?> name = GeneratedColumn<String?>(
'name', aliasedName, false,
type: const StringType());
late final GeneratedColumn<int?> nextUser = GeneratedColumn<int?>(
'next_user', aliasedName, true,
type: const IntType());
late final GeneratedColumn<int?> groupCount = GeneratedColumn<int?>(
'group_count', aliasedName, false,
type: const IntType());
@override
GroupCount createAlias(String alias) {
return GroupCount(attachedDatabase, alias);
}
@override
Query? get query => null;
@override
Set<String> get readTables => const {};
}
class DatabaseAtV5 extends GeneratedDatabase {
DatabaseAtV5(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
DatabaseAtV5.connect(DatabaseConnection c) : super.connect(c);
late final Users users = Users(this);
late final Groups groups = Groups(this);
late final GroupCount groupCount = GroupCount(this);
@override
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
@override
List<DatabaseSchemaEntity> get allSchemaEntities => [users, groups];
List<DatabaseSchemaEntity> get allSchemaEntities =>
[users, groups, groupCount];
@override
int get schemaVersion => 5;
}

View File

@ -8,4 +8,10 @@ CREATE TABLE "groups" (
owner INTEGER NOT NULL REFERENCES users (id),
PRIMARY KEY (id)
);
);
-- This view was added in schema version 5
CREATE VIEW group_count AS SELECT
users.*,
(SELECT COUNT(*) FROM "groups" WHERE owner = users.id) AS group_count
FROM users;

View File

@ -117,8 +117,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
return UsersData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);

View File

@ -140,8 +140,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
return UsersData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);

View File

@ -140,8 +140,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
return UsersData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);
@ -363,8 +361,6 @@ class Groups extends Table with TableInfo<Groups, GroupsData> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
GroupsData map(Map<String, dynamic> data, {String? tablePrefix}) {
return GroupsData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);

View File

@ -142,8 +142,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
return UsersData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);
@ -365,8 +363,6 @@ class Groups extends Table with TableInfo<Groups, GroupsData> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
GroupsData map(Map<String, dynamic> data, {String? tablePrefix}) {
return GroupsData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);

View File

@ -174,8 +174,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
return UsersData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);
@ -397,8 +395,6 @@ class Groups extends Table with TableInfo<Groups, GroupsData> {
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
List<Set<GeneratedColumn>> get uniqueKeys => [];
@override
GroupsData map(Map<String, dynamic> data, {String? tablePrefix}) {
return GroupsData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);
@ -415,15 +411,136 @@ class Groups extends Table with TableInfo<Groups, GroupsData> {
bool get dontWriteConstraints => true;
}
class GroupCountData extends DataClass {
final int id;
final String name;
final int? nextUser;
final int groupCount;
GroupCountData(
{required this.id,
required this.name,
this.nextUser,
required this.groupCount});
factory GroupCountData.fromData(Map<String, dynamic> data, {String? prefix}) {
final effectivePrefix = prefix ?? '';
return GroupCountData(
id: const IntType()
.mapFromDatabaseResponse(data['${effectivePrefix}id'])!,
name: const StringType()
.mapFromDatabaseResponse(data['${effectivePrefix}name'])!,
nextUser: const IntType()
.mapFromDatabaseResponse(data['${effectivePrefix}next_user']),
groupCount: const IntType()
.mapFromDatabaseResponse(data['${effectivePrefix}group_count'])!,
);
}
factory GroupCountData.fromJson(Map<String, dynamic> json,
{ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return GroupCountData(
id: serializer.fromJson<int>(json['id']),
name: serializer.fromJson<String>(json['name']),
nextUser: serializer.fromJson<int?>(json['nextUser']),
groupCount: serializer.fromJson<int>(json['groupCount']),
);
}
@override
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'name': serializer.toJson<String>(name),
'nextUser': serializer.toJson<int?>(nextUser),
'groupCount': serializer.toJson<int>(groupCount),
};
}
GroupCountData copyWith(
{int? id, String? name, int? nextUser, int? groupCount}) =>
GroupCountData(
id: id ?? this.id,
name: name ?? this.name,
nextUser: nextUser ?? this.nextUser,
groupCount: groupCount ?? this.groupCount,
);
@override
String toString() {
return (StringBuffer('GroupCountData(')
..write('id: $id, ')
..write('name: $name, ')
..write('nextUser: $nextUser, ')
..write('groupCount: $groupCount')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, name, nextUser, groupCount);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is GroupCountData &&
other.id == this.id &&
other.name == this.name &&
other.nextUser == this.nextUser &&
other.groupCount == this.groupCount);
}
class GroupCount extends ViewInfo<GroupCount, GroupCountData>
implements HasResultSet {
final String? _alias;
@override
final DatabaseAtV5 attachedDatabase;
GroupCount(this.attachedDatabase, [this._alias]);
@override
List<GeneratedColumn> get $columns => [id, name, nextUser, groupCount];
@override
String get aliasedName => _alias ?? entityName;
@override
String get entityName => 'group_count';
@override
String? get createViewStmt => null;
@override
GroupCount get asDslTable => this;
@override
GroupCountData map(Map<String, dynamic> data, {String? tablePrefix}) {
return GroupCountData.fromData(data,
prefix: tablePrefix != null ? '$tablePrefix.' : null);
}
late final GeneratedColumn<int?> id =
GeneratedColumn<int?>('id', aliasedName, false, type: const IntType());
late final GeneratedColumn<String?> name = GeneratedColumn<String?>(
'name', aliasedName, false,
type: const StringType());
late final GeneratedColumn<int?> nextUser = GeneratedColumn<int?>(
'next_user', aliasedName, true,
type: const IntType());
late final GeneratedColumn<int?> groupCount = GeneratedColumn<int?>(
'group_count', aliasedName, false,
type: const IntType());
@override
GroupCount createAlias(String alias) {
return GroupCount(attachedDatabase, alias);
}
@override
Query? get query => null;
@override
Set<String> get readTables => const {};
}
class DatabaseAtV5 extends GeneratedDatabase {
DatabaseAtV5(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
DatabaseAtV5.connect(DatabaseConnection c) : super.connect(c);
late final Users users = Users(this);
late final Groups groups = Groups(this);
late final GroupCount groupCount = GroupCount(this);
@override
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
@override
List<DatabaseSchemaEntity> get allSchemaEntities => [users, groups];
List<DatabaseSchemaEntity> get allSchemaEntities =>
[users, groups, groupCount];
@override
int get schemaVersion => 5;
}

View File

@ -8,6 +8,8 @@ import 'generated/schema.dart';
import 'generated/schema_v1.dart' as v1;
import 'generated/schema_v2.dart' as v2;
import 'generated/schema_v4.dart' as v4;
import 'generated/schema_v5.dart' as v5;
void main() {
driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
@ -61,4 +63,39 @@ void main() {
await verifier.migrateAndValidate(db, 5);
await db.close();
});
test('view works after upgrade from v4 to v5', () async {
final schema = await verifier.schemaAt(4);
final oldDb = v4.DatabaseAtV4.connect(schema.newConnection());
await oldDb.batch((batch) {
batch
..insert(oldDb.users, v4.UsersCompanion.insert(id: Value(1)))
..insert(oldDb.users, v4.UsersCompanion.insert(id: Value(2)))
..insert(
oldDb.groups, v4.GroupsCompanion.insert(title: 'Test', owner: 1));
});
await oldDb.close();
// Run the migration and verify that it adds the view.
final db = Database(schema.newConnection());
await verifier.migrateAndValidate(db, 5);
await db.close();
// Make sure the view works!
final migratedDb = v5.DatabaseAtV5.connect(schema.newConnection());
final viewCount = await migratedDb.select(migratedDb.groupCount).get();
expect(
viewCount,
contains(isA<v5.GroupCountData>()
.having((e) => e.id, 'id', 1)
.having((e) => e.groupCount, 'groupCount', 1)));
expect(
viewCount,
contains(isA<v5.GroupCountData>()
.having((e) => e.id, 'id', 2)
.having((e) => e.groupCount, 'groupCount', 0)));
await migratedDb.close();
});
}