mirror of https://github.com/AMT-Cheif/drift.git
Support drift-defined views schema tools (#1813)
This commit is contained in:
parent
d0694f9d65
commit
80c8c86031
|
@ -60,6 +60,22 @@ class SchemaWriter {
|
||||||
'name': entity.name,
|
'name': entity.name,
|
||||||
'sql': entity.createStmt,
|
'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) {
|
} else if (entity is SpecialQuery) {
|
||||||
type = 'special-query';
|
type = 'special-query';
|
||||||
data = {
|
data = {
|
||||||
|
@ -200,6 +216,9 @@ class SchemaReader {
|
||||||
case 'table':
|
case 'table':
|
||||||
entity = _readTable(content);
|
entity = _readTable(content);
|
||||||
break;
|
break;
|
||||||
|
case 'view':
|
||||||
|
entity = _readView(content);
|
||||||
|
break;
|
||||||
case 'special-query':
|
case 'special-query':
|
||||||
// Not relevant for the schema.
|
// Not relevant for the schema.
|
||||||
return;
|
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) {
|
MoorColumn _readColumn(Map<String, dynamic> data) {
|
||||||
final name = data['name'] as String;
|
final name = data['name'] as String;
|
||||||
final moorType = ColumnType.values
|
final moorType = ColumnType.values
|
||||||
|
|
|
@ -40,6 +40,8 @@ CREATE TRIGGER delete_empty_groups AFTER DELETE ON group_members BEGIN
|
||||||
END;
|
END;
|
||||||
|
|
||||||
CREATE INDEX groups_name ON "groups"(name);
|
CREATE INDEX groups_name ON "groups"(name);
|
||||||
|
|
||||||
|
CREATE VIEW my_view AS SELECT id FROM "groups";
|
||||||
''',
|
''',
|
||||||
'foo|lib/main.dart': '''
|
'foo|lib/main.dart': '''
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
|
@ -281,6 +283,33 @@ const expected = r'''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 5,
|
"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": [
|
"references": [
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
|
@ -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":[]}]}}]}
|
|
@ -44,6 +44,9 @@ class Database extends _$Database {
|
||||||
} else if (target == 5) {
|
} else if (target == 5) {
|
||||||
// Just add a new column that was added in version 5;
|
// Just add a new column that was added in version 5;
|
||||||
await m.addColumn(users, users.nextUser);
|
await m.addColumn(users, users.nextUser);
|
||||||
|
|
||||||
|
// And create the view on users
|
||||||
|
await m.createView(groupCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -204,8 +204,6 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
User map(Map<String, dynamic> data, {String? tablePrefix}) {
|
User map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return User.fromData(data,
|
return User.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
@ -454,8 +452,6 @@ class Groups extends Table with TableInfo<Groups, Group> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
Group map(Map<String, dynamic> data, {String? tablePrefix}) {
|
Group map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return Group.fromData(data,
|
return Group.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
@ -472,13 +468,135 @@ class Groups extends Table with TableInfo<Groups, Group> {
|
||||||
bool get dontWriteConstraints => true;
|
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 {
|
abstract class _$Database extends GeneratedDatabase {
|
||||||
_$Database(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
_$Database(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
||||||
_$Database.connect(DatabaseConnection c) : super.connect(c);
|
_$Database.connect(DatabaseConnection c) : super.connect(c);
|
||||||
late final $UsersTable users = $UsersTable(this);
|
late final $UsersTable users = $UsersTable(this);
|
||||||
late final Groups groups = Groups(this);
|
late final Groups groups = Groups(this);
|
||||||
|
late final GroupCount groupCount = GroupCount(this);
|
||||||
@override
|
@override
|
||||||
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
||||||
@override
|
@override
|
||||||
List<DatabaseSchemaEntity> get allSchemaEntities => [users, groups];
|
List<DatabaseSchemaEntity> get allSchemaEntities =>
|
||||||
|
[users, groups, groupCount];
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,6 @@ class Users extends Table with TableInfo {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
throw UnsupportedError('TableInfo.map in schema verification code');
|
throw UnsupportedError('TableInfo.map in schema verification code');
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ class Users extends Table with TableInfo {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
throw UnsupportedError('TableInfo.map in schema verification code');
|
throw UnsupportedError('TableInfo.map in schema verification code');
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ class Users extends Table with TableInfo {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
throw UnsupportedError('TableInfo.map in schema verification code');
|
throw UnsupportedError('TableInfo.map in schema verification code');
|
||||||
}
|
}
|
||||||
|
@ -74,8 +72,6 @@ class Groups extends Table with TableInfo {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
throw UnsupportedError('TableInfo.map in schema verification code');
|
throw UnsupportedError('TableInfo.map in schema verification code');
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,6 @@ class Users extends Table with TableInfo {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
throw UnsupportedError('TableInfo.map in schema verification code');
|
throw UnsupportedError('TableInfo.map in schema verification code');
|
||||||
}
|
}
|
||||||
|
@ -76,8 +74,6 @@ class Groups extends Table with TableInfo {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
throw UnsupportedError('TableInfo.map in schema verification code');
|
throw UnsupportedError('TableInfo.map in schema verification code');
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,6 @@ class Users extends Table with TableInfo {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
throw UnsupportedError('TableInfo.map in schema verification code');
|
throw UnsupportedError('TableInfo.map in schema verification code');
|
||||||
}
|
}
|
||||||
|
@ -81,8 +79,6 @@ class Groups extends Table with TableInfo {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
Never map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
throw UnsupportedError('TableInfo.map in schema verification code');
|
throw UnsupportedError('TableInfo.map in schema verification code');
|
||||||
}
|
}
|
||||||
|
@ -98,15 +94,59 @@ class Groups extends Table with TableInfo {
|
||||||
bool get dontWriteConstraints => true;
|
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 {
|
class DatabaseAtV5 extends GeneratedDatabase {
|
||||||
DatabaseAtV5(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
DatabaseAtV5(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
||||||
DatabaseAtV5.connect(DatabaseConnection c) : super.connect(c);
|
DatabaseAtV5.connect(DatabaseConnection c) : super.connect(c);
|
||||||
late final Users users = Users(this);
|
late final Users users = Users(this);
|
||||||
late final Groups groups = Groups(this);
|
late final Groups groups = Groups(this);
|
||||||
|
late final GroupCount groupCount = GroupCount(this);
|
||||||
@override
|
@override
|
||||||
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
||||||
@override
|
@override
|
||||||
List<DatabaseSchemaEntity> get allSchemaEntities => [users, groups];
|
List<DatabaseSchemaEntity> get allSchemaEntities =>
|
||||||
|
[users, groups, groupCount];
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 5;
|
int get schemaVersion => 5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,3 +9,9 @@ CREATE TABLE "groups" (
|
||||||
|
|
||||||
PRIMARY KEY (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;
|
||||||
|
|
|
@ -117,8 +117,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return UsersData.fromData(data,
|
return UsersData.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
|
|
@ -140,8 +140,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return UsersData.fromData(data,
|
return UsersData.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
|
|
@ -140,8 +140,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return UsersData.fromData(data,
|
return UsersData.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
@ -363,8 +361,6 @@ class Groups extends Table with TableInfo<Groups, GroupsData> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
GroupsData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
GroupsData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return GroupsData.fromData(data,
|
return GroupsData.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
|
|
@ -142,8 +142,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return UsersData.fromData(data,
|
return UsersData.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
@ -365,8 +363,6 @@ class Groups extends Table with TableInfo<Groups, GroupsData> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
GroupsData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
GroupsData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return GroupsData.fromData(data,
|
return GroupsData.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
|
|
@ -174,8 +174,6 @@ class Users extends Table with TableInfo<Users, UsersData> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
UsersData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return UsersData.fromData(data,
|
return UsersData.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
@ -397,8 +395,6 @@ class Groups extends Table with TableInfo<Groups, GroupsData> {
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
List<Set<GeneratedColumn>> get uniqueKeys => [];
|
|
||||||
@override
|
|
||||||
GroupsData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
GroupsData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
return GroupsData.fromData(data,
|
return GroupsData.fromData(data,
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
@ -415,15 +411,136 @@ class Groups extends Table with TableInfo<Groups, GroupsData> {
|
||||||
bool get dontWriteConstraints => true;
|
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 {
|
class DatabaseAtV5 extends GeneratedDatabase {
|
||||||
DatabaseAtV5(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
DatabaseAtV5(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
||||||
DatabaseAtV5.connect(DatabaseConnection c) : super.connect(c);
|
DatabaseAtV5.connect(DatabaseConnection c) : super.connect(c);
|
||||||
late final Users users = Users(this);
|
late final Users users = Users(this);
|
||||||
late final Groups groups = Groups(this);
|
late final Groups groups = Groups(this);
|
||||||
|
late final GroupCount groupCount = GroupCount(this);
|
||||||
@override
|
@override
|
||||||
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
||||||
@override
|
@override
|
||||||
List<DatabaseSchemaEntity> get allSchemaEntities => [users, groups];
|
List<DatabaseSchemaEntity> get allSchemaEntities =>
|
||||||
|
[users, groups, groupCount];
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 5;
|
int get schemaVersion => 5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import 'generated/schema.dart';
|
||||||
|
|
||||||
import 'generated/schema_v1.dart' as v1;
|
import 'generated/schema_v1.dart' as v1;
|
||||||
import 'generated/schema_v2.dart' as v2;
|
import 'generated/schema_v2.dart' as v2;
|
||||||
|
import 'generated/schema_v4.dart' as v4;
|
||||||
|
import 'generated/schema_v5.dart' as v5;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||||
|
@ -61,4 +63,39 @@ void main() {
|
||||||
await verifier.migrateAndValidate(db, 5);
|
await verifier.migrateAndValidate(db, 5);
|
||||||
await db.close();
|
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();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue