diff --git a/drift_dev/lib/src/analyzer/options.dart b/drift_dev/lib/src/analyzer/options.dart index 23091a31..54f9f6e0 100644 --- a/drift_dev/lib/src/analyzer/options.dart +++ b/drift_dev/lib/src/analyzer/options.dart @@ -12,7 +12,7 @@ part 'options.g.dart'; anyMap: true, disallowUnrecognizedKeys: true, fieldRename: FieldRename.snake, - createToJson: false, + createToJson: true, ) class DriftOptions { static const _defaultSqliteVersion = SqliteVersion.v3(34); @@ -191,6 +191,8 @@ class DriftOptions { SqliteVersion get sqliteVersion { return sqliteOptions?.version ?? _defaultSqliteVersion; } + + Map toJson() => _$DriftOptionsToJson(this); } @JsonSerializable() diff --git a/drift_dev/lib/src/analyzer/options.g.dart b/drift_dev/lib/src/analyzer/options.g.dart index 39a1299a..5b6fe796 100644 --- a/drift_dev/lib/src/analyzer/options.g.dart +++ b/drift_dev/lib/src/analyzer/options.g.dart @@ -115,6 +115,36 @@ DriftOptions _$DriftOptionsFromJson(Map json) => $checkedCreate( }, ); +Map _$DriftOptionsToJson(DriftOptions instance) => + { + 'write_from_json_string_constructor': + instance.generateFromJsonStringConstructor, + 'override_hash_and_equals_in_result_sets': + instance.overrideHashAndEqualsInResultSets, + 'compact_query_methods': instance.compactQueryMethods, + 'skip_verification_code': instance.skipVerificationCode, + 'use_data_class_name_for_companions': + instance.useDataClassNameForCompanions, + 'use_column_name_as_json_key_when_defined_in_moor_file': + instance.useColumnNameAsJsonKeyWhenDefinedInMoorFile, + 'generate_connect_constructor': instance.generateConnectConstructor, + 'sqlite_modules': + instance.modules.map((e) => _$SqlModuleEnumMap[e]!).toList(), + 'sqlite': instance.sqliteAnalysisOptions, + 'sql': instance.dialect, + 'eagerly_load_dart_ast': instance.eagerlyLoadDartAst, + 'data_class_to_companions': instance.dataClassToCompanions, + 'mutable_classes': instance.generateMutableClasses, + 'raw_result_set_data': instance.rawResultSetData, + 'apply_converters_on_variables': instance.applyConvertersOnVariables, + 'generate_values_in_copy_with': instance.generateValuesInCopyWith, + 'named_parameters': instance.generateNamedParameters, + 'named_parameters_always_required': + instance.namedParametersAlwaysRequired, + 'scoped_dart_components': instance.scopedDartComponents, + 'store_date_time_values_as_text': instance.storeDateTimeValuesAsText, + }; + const _$SqlModuleEnumMap = { SqlModule.json1: 'json1', SqlModule.fts5: 'fts5', diff --git a/drift_dev/lib/src/cli/commands/schema/dump.dart b/drift_dev/lib/src/cli/commands/schema/dump.dart index 6e1f49de..0f167ee4 100644 --- a/drift_dev/lib/src/cli/commands/schema/dump.dart +++ b/drift_dev/lib/src/cli/commands/schema/dump.dart @@ -50,7 +50,7 @@ class DumpSchemaCommand extends Command { } final db = result.declaredDatabases.single; - final writer = SchemaWriter(db); + final writer = SchemaWriter(db, options: cli.project.moorOptions); var target = rest[1]; // This command is most commonly used to write into diff --git a/drift_dev/lib/src/cli/commands/schema/generate_utils.dart b/drift_dev/lib/src/cli/commands/schema/generate_utils.dart index 9ca448ab..25297b8d 100644 --- a/drift_dev/lib/src/cli/commands/schema/generate_utils.dart +++ b/drift_dev/lib/src/cli/commands/schema/generate_utils.dart @@ -9,6 +9,8 @@ import 'package:drift_dev/src/services/schema/schema_files.dart'; import 'package:drift_dev/writer.dart'; import 'package:path/path.dart' as p; +import '../../../analyzer/options.dart'; + class GenerateUtilsCommand extends Command { final MoorCli cli; @@ -78,9 +80,8 @@ class GenerateUtilsCommand extends Command { 'Wrote ${schema.length + 1} files into ${p.relative(outputDir.path)}'); } - Future>> _parseSchema( - Directory directory) async { - final results = >{}; + Future> _parseSchema(Directory directory) async { + final results = {}; await for (final entity in directory.list()) { final basename = p.basename(entity.path); @@ -92,7 +93,8 @@ class GenerateUtilsCommand extends Command { final rawData = json.decode(await entity.readAsString()); final schema = SchemaReader.readJson(rawData as Map); - results[version] = schema.entities.toList(); + results[version] = + _ExportedSchema(schema.entities.toList(), schema.options); } return results; @@ -101,13 +103,20 @@ class GenerateUtilsCommand extends Command { Future _writeSchemaFile( Directory output, int version, - List entities, + _ExportedSchema schema, bool dataClasses, bool companions, bool isForMoor, ) { + // let serialized options take precedence, otherwise use current options + // from project. + final options = DriftOptions.fromJson({ + ...cli.project.moorOptions.toJson(), + ...schema.options, + }); + final writer = Writer( - cli.project.moorOptions, + options, generationOptions: GenerationOptions( forSchema: version, writeCompanions: companions, @@ -131,7 +140,7 @@ class GenerateUtilsCommand extends Command { declaredQueries: const [], declaredIncludes: const [], declaredTables: const [], - )..entities = entities; + )..entities = schema.schema; DatabaseWriter(db, writer.child()).write(); return file.writeAsString(_dartfmt.format(writer.writeGenerated())); @@ -186,3 +195,10 @@ class GenerateUtilsCommand extends Command { static final _dartfmt = DartFormatter(); static const _prefix = '// GENERATED CODE, DO NOT EDIT BY HAND.'; } + +class _ExportedSchema { + final List schema; + final Map options; + + _ExportedSchema(this.schema, this.options); +} diff --git a/drift_dev/lib/src/services/schema/schema_files.dart b/drift_dev/lib/src/services/schema/schema_files.dart index 9b36a4d3..0f78aeb5 100644 --- a/drift_dev/lib/src/services/schema/schema_files.dart +++ b/drift_dev/lib/src/services/schema/schema_files.dart @@ -5,19 +5,19 @@ import 'package:sqlparser/sqlparser.dart'; import '../../writer/utils/column_constraints.dart'; -const _infoVersion = '0.1.0-dev-preview'; +const _infoVersion = '1.0.0'; /// Utilities to transform moor schema entities to json. class SchemaWriter { - static const _exportOptions = DriftOptions.defaults(); - /// The parsed and resolved database for which the schema should be written. final Database db; + final DriftOptions options; + final Map _entityIds = {}; int _maxId = 0; - SchemaWriter(this.db); + SchemaWriter(this.db, {this.options = const DriftOptions.defaults()}); int _idOf(DriftSchemaEntity entity) { return _entityIds.putIfAbsent(entity, () => _maxId++); @@ -27,15 +27,24 @@ class SchemaWriter { return { '_meta': { 'description': 'This file contains a serialized version of schema ' - 'entities for moor.', + 'entities for drift.', 'version': _infoVersion, }, + 'options': _serializeOptions(), 'entities': [ for (final entity in db.entities) _entityToJson(entity), ], }; } + Map _serializeOptions() { + const relevantKeys = {'store_date_time_values_as_text'}; + final asJson = options.toJson() + ..removeWhere((key, _) => !relevantKeys.contains(key)); + + return asJson; + } + Map _entityToJson(DriftSchemaEntity entity) { String type; Map data; @@ -51,7 +60,7 @@ class SchemaWriter { for (final ref in entity.bodyReferences) _idOf(ref), ], 'name': entity.displayName, - 'sql': entity.createSql(_exportOptions), + 'sql': entity.createSql(options), }; } else if (entity is MoorIndex) { type = 'index'; @@ -160,6 +169,7 @@ class SchemaReader { final Set _currentlyProcessing = {}; final SqlEngine _engine = SqlEngine(); + Map options = const {}; SchemaReader._(); @@ -170,6 +180,13 @@ class SchemaReader { Iterable get entities => _entitiesById.values; void _read(Map json) { + // Read drift options if they are part of the schema file. + final optionsInJson = json['options'] as Map?; + options = optionsInJson ?? + { + 'store_date_time_values_as_text': false, + }; + final entities = json['entities'] as List; for (final raw in entities) { diff --git a/drift_dev/test/services/schema/writer_test.dart b/drift_dev/test/services/schema/writer_test.dart index 51522b08..2a906ac2 100644 --- a/drift_dev/test/services/schema/writer_test.dart +++ b/drift_dev/test/services/schema/writer_test.dart @@ -74,11 +74,19 @@ class Database {} final schemaJson = SchemaWriter(db).createSchemaJson(); expect(schemaJson, json.decode(expected)); + + final schemaWithOptions = SchemaWriter( + db, + options: const DriftOptions.defaults(storeDateTimeValuesAsText: true), + ).createSchemaJson(); + expect( + schemaWithOptions['options'], {'store_date_time_values_as_text': true}); }); test('can generate code from schema json', () { - final reader = - SchemaReader.readJson(json.decode(expected) as Map); + final serializedSchema = json.decode(expected) as Map; + + final reader = SchemaReader.readJson(serializedSchema); final fakeDb = Database()..entities = [...reader.entities]; // Write the database. Not crashing is good enough for us here, we have @@ -92,8 +100,11 @@ class Database {} const expected = r''' { "_meta": { - "description": "This file contains a serialized version of schema entities for moor.", - "version": "0.1.0-dev-preview" + "description": "This file contains a serialized version of schema entities for drift.", + "version": "1.0.0" + }, + "options": { + "store_date_time_values_as_text": false }, "entities": [ { diff --git a/examples/migrations_example/build.yaml b/examples/migrations_example/build.yaml index 4c6ca9c6..0996a36e 100644 --- a/examples/migrations_example/build.yaml +++ b/examples/migrations_example/build.yaml @@ -4,3 +4,4 @@ targets: drift_dev: options: generate_connect_constructor: true + store_date_time_values_as_text: true diff --git a/examples/migrations_example/drift_migrations/drift_schema_v6.json b/examples/migrations_example/drift_migrations/drift_schema_v6.json new file mode 100644 index 00000000..7cfd7fd5 --- /dev/null +++ b/examples/migrations_example/drift_migrations/drift_schema_v6.json @@ -0,0 +1 @@ +{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.0.0"},"options":{"store_date_time_values_as_text":true},"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":"birthday","getter_name":"birthday","moor_type":"ColumnType.datetime","nullable":true,"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,"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('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":"birthday","getter_name":"birthday","moor_type":"ColumnType.datetime","nullable":true,"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":[]}]}}]} \ No newline at end of file diff --git a/examples/migrations_example/lib/database.dart b/examples/migrations_example/lib/database.dart index 33105a80..097751d8 100644 --- a/examples/migrations_example/lib/database.dart +++ b/examples/migrations_example/lib/database.dart @@ -9,7 +9,7 @@ part 'database.g.dart'; @DriftDatabase(include: {'tables.drift'}) class Database extends _$Database { @override - int get schemaVersion => 5; + int get schemaVersion => 6; Database(DatabaseConnection connection) : super.connect(connection); @@ -47,6 +47,8 @@ class Database extends _$Database { // And create the view on users await m.createView(groupCount); + } else if (target == 6) { + await m.addColumn(users, users.birthday); } } }, diff --git a/examples/migrations_example/lib/database.g.dart b/examples/migrations_example/lib/database.g.dart index 6ce7988f..ae50b4e1 100644 --- a/examples/migrations_example/lib/database.g.dart +++ b/examples/migrations_example/lib/database.g.dart @@ -10,13 +10,18 @@ part of 'database.dart'; class User extends DataClass implements Insertable { final int id; final String name; + final DateTime? birthday; final int? nextUser; - const User({required this.id, required this.name, this.nextUser}); + const User( + {required this.id, required this.name, this.birthday, this.nextUser}); @override Map toColumns(bool nullToAbsent) { final map = {}; map['id'] = Variable(id); map['name'] = Variable(name); + if (!nullToAbsent || birthday != null) { + map['birthday'] = Variable(birthday); + } if (!nullToAbsent || nextUser != null) { map['next_user'] = Variable(nextUser); } @@ -27,6 +32,9 @@ class User extends DataClass implements Insertable { return UsersCompanion( id: Value(id), name: Value(name), + birthday: birthday == null && nullToAbsent + ? const Value.absent() + : Value(birthday), nextUser: nextUser == null && nullToAbsent ? const Value.absent() : Value(nextUser), @@ -39,6 +47,7 @@ class User extends DataClass implements Insertable { return User( id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), + birthday: serializer.fromJson(json['birthday']), nextUser: serializer.fromJson(json['nextUser']), ); } @@ -48,13 +57,16 @@ class User extends DataClass implements Insertable { return { 'id': serializer.toJson(id), 'name': serializer.toJson(name), + 'birthday': serializer.toJson(birthday), 'nextUser': serializer.toJson(nextUser), }; } - User copyWith({int? id, String? name, int? nextUser}) => User( + User copyWith({int? id, String? name, DateTime? birthday, int? nextUser}) => + User( id: id ?? this.id, name: name ?? this.name, + birthday: birthday ?? this.birthday, nextUser: nextUser ?? this.nextUser, ); @override @@ -62,53 +74,64 @@ class User extends DataClass implements Insertable { return (StringBuffer('User(') ..write('id: $id, ') ..write('name: $name, ') + ..write('birthday: $birthday, ') ..write('nextUser: $nextUser') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(id, name, nextUser); + int get hashCode => Object.hash(id, name, birthday, nextUser); @override bool operator ==(Object other) => identical(this, other) || (other is User && other.id == this.id && other.name == this.name && + other.birthday == this.birthday && other.nextUser == this.nextUser); } class UsersCompanion extends UpdateCompanion { final Value id; final Value name; + final Value birthday; final Value nextUser; const UsersCompanion({ this.id = const Value.absent(), this.name = const Value.absent(), + this.birthday = const Value.absent(), this.nextUser = const Value.absent(), }); UsersCompanion.insert({ this.id = const Value.absent(), this.name = const Value.absent(), + this.birthday = const Value.absent(), this.nextUser = const Value.absent(), }); static Insertable custom({ Expression? id, Expression? name, + Expression? birthday, Expression? nextUser, }) { return RawValuesInsertable({ if (id != null) 'id': id, if (name != null) 'name': name, + if (birthday != null) 'birthday': birthday, if (nextUser != null) 'next_user': nextUser, }); } UsersCompanion copyWith( - {Value? id, Value? name, Value? nextUser}) { + {Value? id, + Value? name, + Value? birthday, + Value? nextUser}) { return UsersCompanion( id: id ?? this.id, name: name ?? this.name, + birthday: birthday ?? this.birthday, nextUser: nextUser ?? this.nextUser, ); } @@ -122,6 +145,9 @@ class UsersCompanion extends UpdateCompanion { if (name.present) { map['name'] = Variable(name.value); } + if (birthday.present) { + map['birthday'] = Variable(birthday.value); + } if (nextUser.present) { map['next_user'] = Variable(nextUser.value); } @@ -133,6 +159,7 @@ class UsersCompanion extends UpdateCompanion { return (StringBuffer('UsersCompanion(') ..write('id: $id, ') ..write('name: $name, ') + ..write('birthday: $birthday, ') ..write('nextUser: $nextUser') ..write(')')) .toString(); @@ -158,6 +185,11 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> { type: DriftSqlType.string, requiredDuringInsert: false, defaultValue: const Constant('name')); + final VerificationMeta _birthdayMeta = const VerificationMeta('birthday'); + @override + late final GeneratedColumn birthday = GeneratedColumn( + 'birthday', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); final VerificationMeta _nextUserMeta = const VerificationMeta('nextUser'); @override late final GeneratedColumn nextUser = GeneratedColumn( @@ -166,7 +198,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> { requiredDuringInsert: false, defaultConstraints: 'REFERENCES users (id)'); @override - List get $columns => [id, name, nextUser]; + List get $columns => [id, name, birthday, nextUser]; @override String get aliasedName => _alias ?? 'users'; @override @@ -183,6 +215,10 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> { context.handle( _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); } + if (data.containsKey('birthday')) { + context.handle(_birthdayMeta, + birthday.isAcceptableOrUnknown(data['birthday']!, _birthdayMeta)); + } if (data.containsKey('next_user')) { context.handle(_nextUserMeta, nextUser.isAcceptableOrUnknown(data['next_user']!, _nextUserMeta)); @@ -200,6 +236,8 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> { .read(DriftSqlType.int, data['${effectivePrefix}id'])!, name: attachedDatabase.options.types .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + birthday: attachedDatabase.options.types + .read(DriftSqlType.dateTime, data['${effectivePrefix}birthday']), nextUser: attachedDatabase.options.types .read(DriftSqlType.int, data['${effectivePrefix}next_user']), ); @@ -463,11 +501,13 @@ class Groups extends Table with TableInfo { class GroupCountData extends DataClass { final int id; final String name; + final DateTime? birthday; final int? nextUser; final int groupCount; const GroupCountData( {required this.id, required this.name, + this.birthday, this.nextUser, required this.groupCount}); factory GroupCountData.fromJson(Map json, @@ -476,6 +516,7 @@ class GroupCountData extends DataClass { return GroupCountData( id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), + birthday: serializer.fromJson(json['birthday']), nextUser: serializer.fromJson(json['nextUser']), groupCount: serializer.fromJson(json['groupCount']), ); @@ -486,16 +527,22 @@ class GroupCountData extends DataClass { return { 'id': serializer.toJson(id), 'name': serializer.toJson(name), + 'birthday': serializer.toJson(birthday), 'nextUser': serializer.toJson(nextUser), 'groupCount': serializer.toJson(groupCount), }; } GroupCountData copyWith( - {int? id, String? name, int? nextUser, int? groupCount}) => + {int? id, + String? name, + DateTime? birthday, + int? nextUser, + int? groupCount}) => GroupCountData( id: id ?? this.id, name: name ?? this.name, + birthday: birthday ?? this.birthday, nextUser: nextUser ?? this.nextUser, groupCount: groupCount ?? this.groupCount, ); @@ -504,6 +551,7 @@ class GroupCountData extends DataClass { return (StringBuffer('GroupCountData(') ..write('id: $id, ') ..write('name: $name, ') + ..write('birthday: $birthday, ') ..write('nextUser: $nextUser, ') ..write('groupCount: $groupCount') ..write(')')) @@ -511,13 +559,14 @@ class GroupCountData extends DataClass { } @override - int get hashCode => Object.hash(id, name, nextUser, groupCount); + int get hashCode => Object.hash(id, name, birthday, nextUser, groupCount); @override bool operator ==(Object other) => identical(this, other) || (other is GroupCountData && other.id == this.id && other.name == this.name && + other.birthday == this.birthday && other.nextUser == this.nextUser && other.groupCount == this.groupCount); } @@ -529,7 +578,8 @@ class GroupCount extends ViewInfo final _$Database attachedDatabase; GroupCount(this.attachedDatabase, [this._alias]); @override - List get $columns => [id, name, nextUser, groupCount]; + List get $columns => + [id, name, birthday, nextUser, groupCount]; @override String get aliasedName => _alias ?? entityName; @override @@ -547,6 +597,8 @@ class GroupCount extends ViewInfo .read(DriftSqlType.int, data['${effectivePrefix}id'])!, name: attachedDatabase.options.types .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + birthday: attachedDatabase.options.types + .read(DriftSqlType.dateTime, data['${effectivePrefix}birthday']), nextUser: attachedDatabase.options.types .read(DriftSqlType.int, data['${effectivePrefix}next_user']), groupCount: attachedDatabase.options.types @@ -559,6 +611,9 @@ class GroupCount extends ViewInfo late final GeneratedColumn name = GeneratedColumn( 'name', aliasedName, false, type: DriftSqlType.string); + late final GeneratedColumn birthday = GeneratedColumn( + 'birthday', aliasedName, true, + type: DriftSqlType.dateTime); late final GeneratedColumn nextUser = GeneratedColumn( 'next_user', aliasedName, true, type: DriftSqlType.int); @@ -587,4 +642,7 @@ abstract class _$Database extends GeneratedDatabase { @override List get allSchemaEntities => [users, groups, groupCount]; + @override + DriftDatabaseOptions get options => + const DriftDatabaseOptions(storeDateTimeAsText: true); } diff --git a/examples/migrations_example/lib/src/generated/schema.dart b/examples/migrations_example/lib/src/generated/schema.dart index 8faa5348..30369645 100644 --- a/examples/migrations_example/lib/src/generated/schema.dart +++ b/examples/migrations_example/lib/src/generated/schema.dart @@ -2,6 +2,7 @@ //@dart=2.12 import 'package:drift/drift.dart'; import 'package:drift_dev/api/migrations.dart'; +import 'schema_v6.dart' as v6; import 'schema_v2.dart' as v2; import 'schema_v3.dart' as v3; import 'schema_v4.dart' as v4; @@ -12,6 +13,8 @@ class GeneratedHelper implements SchemaInstantiationHelper { @override GeneratedDatabase databaseForVersion(QueryExecutor db, int version) { switch (version) { + case 6: + return v6.DatabaseAtV6(db); case 2: return v2.DatabaseAtV2(db); case 3: @@ -23,7 +26,7 @@ class GeneratedHelper implements SchemaInstantiationHelper { case 5: return v5.DatabaseAtV5(db); default: - throw MissingSchemaException(version, const {2, 3, 4, 1, 5}); + throw MissingSchemaException(version, const {6, 2, 3, 4, 1, 5}); } } } diff --git a/examples/migrations_example/lib/src/generated/schema_v6.dart b/examples/migrations_example/lib/src/generated/schema_v6.dart new file mode 100644 index 00000000..fbfd7a02 --- /dev/null +++ b/examples/migrations_example/lib/src/generated/schema_v6.dart @@ -0,0 +1,162 @@ +// GENERATED CODE, DO NOT EDIT BY HAND. +//@dart=2.12 +import 'package:drift/drift.dart'; + +class Users extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Users(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: 'PRIMARY KEY AUTOINCREMENT'); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant('name')); + late final GeneratedColumn birthday = GeneratedColumn( + 'birthday', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn nextUser = GeneratedColumn( + 'next_user', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: 'REFERENCES users (id)'); + @override + List get $columns => [id, name, birthday, nextUser]; + @override + String get aliasedName => _alias ?? 'users'; + @override + String get actualTableName => 'users'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Users createAlias(String alias) { + return Users(attachedDatabase, alias); + } + + @override + bool get dontWriteConstraints => false; +} + +class Groups extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Groups(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL'); + late final GeneratedColumn title = GeneratedColumn( + 'title', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL'); + late final GeneratedColumn deleted = GeneratedColumn( + 'deleted', aliasedName, true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + $customConstraints: 'DEFAULT FALSE', + defaultValue: const CustomExpression('FALSE')); + late final GeneratedColumn owner = GeneratedColumn( + 'owner', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL REFERENCES users (id)'); + @override + List get $columns => [id, title, deleted, owner]; + @override + String get aliasedName => _alias ?? 'groups'; + @override + String get actualTableName => 'groups'; + @override + Set get $primaryKey => {id}; + @override + Never map(Map data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + @override + Groups createAlias(String alias) { + return Groups(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY (id)']; + @override + bool get dontWriteConstraints => true; +} + +class GroupCount extends ViewInfo implements HasResultSet { + final String? _alias; + @override + final DatabaseAtV6 attachedDatabase; + GroupCount(this.attachedDatabase, [this._alias]); + @override + List get $columns => + [id, name, birthday, 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 data, {String? tablePrefix}) { + throw UnsupportedError('TableInfo.map in schema verification code'); + } + + late final GeneratedColumn id = + GeneratedColumn('id', aliasedName, false, type: DriftSqlType.int); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string); + late final GeneratedColumn birthday = GeneratedColumn( + 'birthday', aliasedName, true, + type: DriftSqlType.dateTime); + late final GeneratedColumn nextUser = GeneratedColumn( + 'next_user', aliasedName, true, + type: DriftSqlType.int); + late final GeneratedColumn groupCount = GeneratedColumn( + 'group_count', aliasedName, false, + type: DriftSqlType.int); + @override + GroupCount createAlias(String alias) { + return GroupCount(attachedDatabase, alias); + } + + @override + Query? get query => null; + @override + Set get readTables => const {}; +} + +class DatabaseAtV6 extends GeneratedDatabase { + DatabaseAtV6(QueryExecutor e) : super(e); + DatabaseAtV6.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 get allTables => allSchemaEntities.whereType(); + @override + List get allSchemaEntities => + [users, groups, groupCount]; + @override + int get schemaVersion => 6; + @override + DriftDatabaseOptions get options => + const DriftDatabaseOptions(storeDateTimeAsText: true); +} diff --git a/examples/migrations_example/lib/tables.dart b/examples/migrations_example/lib/tables.dart index 3bfd3ad6..112da48b 100644 --- a/examples/migrations_example/lib/tables.dart +++ b/examples/migrations_example/lib/tables.dart @@ -6,5 +6,8 @@ class Users extends Table { // added in schema version 2, got a default in version 4 TextColumn get name => text().withDefault(const Constant('name'))(); + // Column added in version 6 + DateTimeColumn get birthday => dateTime().nullable()(); + IntColumn get nextUser => integer().nullable().references(Users, #id)(); } diff --git a/examples/migrations_example/test/generated/schema.dart b/examples/migrations_example/test/generated/schema.dart index 8faa5348..30369645 100644 --- a/examples/migrations_example/test/generated/schema.dart +++ b/examples/migrations_example/test/generated/schema.dart @@ -2,6 +2,7 @@ //@dart=2.12 import 'package:drift/drift.dart'; import 'package:drift_dev/api/migrations.dart'; +import 'schema_v6.dart' as v6; import 'schema_v2.dart' as v2; import 'schema_v3.dart' as v3; import 'schema_v4.dart' as v4; @@ -12,6 +13,8 @@ class GeneratedHelper implements SchemaInstantiationHelper { @override GeneratedDatabase databaseForVersion(QueryExecutor db, int version) { switch (version) { + case 6: + return v6.DatabaseAtV6(db); case 2: return v2.DatabaseAtV2(db); case 3: @@ -23,7 +26,7 @@ class GeneratedHelper implements SchemaInstantiationHelper { case 5: return v5.DatabaseAtV5(db); default: - throw MissingSchemaException(version, const {2, 3, 4, 1, 5}); + throw MissingSchemaException(version, const {6, 2, 3, 4, 1, 5}); } } } diff --git a/examples/migrations_example/test/generated/schema_v1.dart b/examples/migrations_example/test/generated/schema_v1.dart index 041b5409..e4d8d09e 100644 --- a/examples/migrations_example/test/generated/schema_v1.dart +++ b/examples/migrations_example/test/generated/schema_v1.dart @@ -4,7 +4,7 @@ import 'package:drift/drift.dart'; class UsersData extends DataClass implements Insertable { final int id; - UsersData({required this.id}); + const UsersData({required this.id}); @override Map toColumns(bool nullToAbsent) { final map = {}; diff --git a/examples/migrations_example/test/generated/schema_v2.dart b/examples/migrations_example/test/generated/schema_v2.dart index 8fdc1ad5..e949e309 100644 --- a/examples/migrations_example/test/generated/schema_v2.dart +++ b/examples/migrations_example/test/generated/schema_v2.dart @@ -5,7 +5,7 @@ import 'package:drift/drift.dart'; class UsersData extends DataClass implements Insertable { final int id; final String name; - UsersData({required this.id, required this.name}); + const UsersData({required this.id, required this.name}); @override Map toColumns(bool nullToAbsent) { final map = {}; diff --git a/examples/migrations_example/test/generated/schema_v3.dart b/examples/migrations_example/test/generated/schema_v3.dart index 20edf3a7..cfdd8316 100644 --- a/examples/migrations_example/test/generated/schema_v3.dart +++ b/examples/migrations_example/test/generated/schema_v3.dart @@ -5,7 +5,7 @@ import 'package:drift/drift.dart'; class UsersData extends DataClass implements Insertable { final int id; final String name; - UsersData({required this.id, required this.name}); + const UsersData({required this.id, required this.name}); @override Map toColumns(bool nullToAbsent) { final map = {}; @@ -155,7 +155,7 @@ class GroupsData extends DataClass implements Insertable { final String title; final bool? deleted; final int owner; - GroupsData( + const GroupsData( {required this.id, required this.title, this.deleted, diff --git a/examples/migrations_example/test/generated/schema_v4.dart b/examples/migrations_example/test/generated/schema_v4.dart index 3c678acf..5dee9e06 100644 --- a/examples/migrations_example/test/generated/schema_v4.dart +++ b/examples/migrations_example/test/generated/schema_v4.dart @@ -5,7 +5,7 @@ import 'package:drift/drift.dart'; class UsersData extends DataClass implements Insertable { final int id; final String name; - UsersData({required this.id, required this.name}); + const UsersData({required this.id, required this.name}); @override Map toColumns(bool nullToAbsent) { final map = {}; @@ -157,7 +157,7 @@ class GroupsData extends DataClass implements Insertable { final String title; final bool? deleted; final int owner; - GroupsData( + const GroupsData( {required this.id, required this.title, this.deleted, diff --git a/examples/migrations_example/test/generated/schema_v5.dart b/examples/migrations_example/test/generated/schema_v5.dart index fd9ce772..1f8c00d1 100644 --- a/examples/migrations_example/test/generated/schema_v5.dart +++ b/examples/migrations_example/test/generated/schema_v5.dart @@ -6,7 +6,7 @@ class UsersData extends DataClass implements Insertable { final int id; final String name; final int? nextUser; - UsersData({required this.id, required this.name, this.nextUser}); + const UsersData({required this.id, required this.name, this.nextUser}); @override Map toColumns(bool nullToAbsent) { final map = {}; @@ -189,7 +189,7 @@ class GroupsData extends DataClass implements Insertable { final String title; final bool? deleted; final int owner; - GroupsData( + const GroupsData( {required this.id, required this.title, this.deleted, @@ -408,7 +408,7 @@ class GroupCountData extends DataClass { final String name; final int? nextUser; final int groupCount; - GroupCountData( + const GroupCountData( {required this.id, required this.name, this.nextUser, diff --git a/examples/migrations_example/test/generated/schema_v6.dart b/examples/migrations_example/test/generated/schema_v6.dart new file mode 100644 index 00000000..2810bda8 --- /dev/null +++ b/examples/migrations_example/test/generated/schema_v6.dart @@ -0,0 +1,587 @@ +// GENERATED CODE, DO NOT EDIT BY HAND. +//@dart=2.12 +import 'package:drift/drift.dart'; + +class UsersData extends DataClass implements Insertable { + final int id; + final String name; + final DateTime? birthday; + final int? nextUser; + const UsersData( + {required this.id, required this.name, this.birthday, this.nextUser}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + if (!nullToAbsent || birthday != null) { + map['birthday'] = Variable(birthday); + } + if (!nullToAbsent || nextUser != null) { + map['next_user'] = Variable(nextUser); + } + return map; + } + + UsersCompanion toCompanion(bool nullToAbsent) { + return UsersCompanion( + id: Value(id), + name: Value(name), + birthday: birthday == null && nullToAbsent + ? const Value.absent() + : Value(birthday), + nextUser: nextUser == null && nullToAbsent + ? const Value.absent() + : Value(nextUser), + ); + } + + factory UsersData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UsersData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + birthday: serializer.fromJson(json['birthday']), + nextUser: serializer.fromJson(json['nextUser']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'birthday': serializer.toJson(birthday), + 'nextUser': serializer.toJson(nextUser), + }; + } + + UsersData copyWith( + {int? id, String? name, DateTime? birthday, int? nextUser}) => + UsersData( + id: id ?? this.id, + name: name ?? this.name, + birthday: birthday ?? this.birthday, + nextUser: nextUser ?? this.nextUser, + ); + @override + String toString() { + return (StringBuffer('UsersData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('birthday: $birthday, ') + ..write('nextUser: $nextUser') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, birthday, nextUser); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UsersData && + other.id == this.id && + other.name == this.name && + other.birthday == this.birthday && + other.nextUser == this.nextUser); +} + +class UsersCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value birthday; + final Value nextUser; + const UsersCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.birthday = const Value.absent(), + this.nextUser = const Value.absent(), + }); + UsersCompanion.insert({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.birthday = const Value.absent(), + this.nextUser = const Value.absent(), + }); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? birthday, + Expression? nextUser, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (birthday != null) 'birthday': birthday, + if (nextUser != null) 'next_user': nextUser, + }); + } + + UsersCompanion copyWith( + {Value? id, + Value? name, + Value? birthday, + Value? nextUser}) { + return UsersCompanion( + id: id ?? this.id, + name: name ?? this.name, + birthday: birthday ?? this.birthday, + nextUser: nextUser ?? this.nextUser, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (birthday.present) { + map['birthday'] = Variable(birthday.value); + } + if (nextUser.present) { + map['next_user'] = Variable(nextUser.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UsersCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('birthday: $birthday, ') + ..write('nextUser: $nextUser') + ..write(')')) + .toString(); + } +} + +class Users extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Users(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: 'PRIMARY KEY AUTOINCREMENT'); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant('name')); + late final GeneratedColumn birthday = GeneratedColumn( + 'birthday', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn nextUser = GeneratedColumn( + 'next_user', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: 'REFERENCES users (id)'); + @override + List get $columns => [id, name, birthday, nextUser]; + @override + String get aliasedName => _alias ?? 'users'; + @override + String get actualTableName => 'users'; + @override + Set get $primaryKey => {id}; + @override + UsersData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UsersData( + id: attachedDatabase.options.types + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + name: attachedDatabase.options.types + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + birthday: attachedDatabase.options.types + .read(DriftSqlType.dateTime, data['${effectivePrefix}birthday']), + nextUser: attachedDatabase.options.types + .read(DriftSqlType.int, data['${effectivePrefix}next_user']), + ); + } + + @override + Users createAlias(String alias) { + return Users(attachedDatabase, alias); + } + + @override + bool get dontWriteConstraints => false; +} + +class GroupsData extends DataClass implements Insertable { + final int id; + final String title; + final bool? deleted; + final int owner; + const GroupsData( + {required this.id, + required this.title, + this.deleted, + required this.owner}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['title'] = Variable(title); + if (!nullToAbsent || deleted != null) { + map['deleted'] = Variable(deleted); + } + map['owner'] = Variable(owner); + return map; + } + + GroupsCompanion toCompanion(bool nullToAbsent) { + return GroupsCompanion( + id: Value(id), + title: Value(title), + deleted: deleted == null && nullToAbsent + ? const Value.absent() + : Value(deleted), + owner: Value(owner), + ); + } + + factory GroupsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return GroupsData( + id: serializer.fromJson(json['id']), + title: serializer.fromJson(json['title']), + deleted: serializer.fromJson(json['deleted']), + owner: serializer.fromJson(json['owner']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'title': serializer.toJson(title), + 'deleted': serializer.toJson(deleted), + 'owner': serializer.toJson(owner), + }; + } + + GroupsData copyWith({int? id, String? title, bool? deleted, int? owner}) => + GroupsData( + id: id ?? this.id, + title: title ?? this.title, + deleted: deleted ?? this.deleted, + owner: owner ?? this.owner, + ); + @override + String toString() { + return (StringBuffer('GroupsData(') + ..write('id: $id, ') + ..write('title: $title, ') + ..write('deleted: $deleted, ') + ..write('owner: $owner') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, title, deleted, owner); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is GroupsData && + other.id == this.id && + other.title == this.title && + other.deleted == this.deleted && + other.owner == this.owner); +} + +class GroupsCompanion extends UpdateCompanion { + final Value id; + final Value title; + final Value deleted; + final Value owner; + const GroupsCompanion({ + this.id = const Value.absent(), + this.title = const Value.absent(), + this.deleted = const Value.absent(), + this.owner = const Value.absent(), + }); + GroupsCompanion.insert({ + this.id = const Value.absent(), + required String title, + this.deleted = const Value.absent(), + required int owner, + }) : title = Value(title), + owner = Value(owner); + static Insertable custom({ + Expression? id, + Expression? title, + Expression? deleted, + Expression? owner, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (title != null) 'title': title, + if (deleted != null) 'deleted': deleted, + if (owner != null) 'owner': owner, + }); + } + + GroupsCompanion copyWith( + {Value? id, + Value? title, + Value? deleted, + Value? owner}) { + return GroupsCompanion( + id: id ?? this.id, + title: title ?? this.title, + deleted: deleted ?? this.deleted, + owner: owner ?? this.owner, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (title.present) { + map['title'] = Variable(title.value); + } + if (deleted.present) { + map['deleted'] = Variable(deleted.value); + } + if (owner.present) { + map['owner'] = Variable(owner.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('GroupsCompanion(') + ..write('id: $id, ') + ..write('title: $title, ') + ..write('deleted: $deleted, ') + ..write('owner: $owner') + ..write(')')) + .toString(); + } +} + +class Groups extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Groups(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + $customConstraints: 'NOT NULL'); + late final GeneratedColumn title = GeneratedColumn( + 'title', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL'); + late final GeneratedColumn deleted = GeneratedColumn( + 'deleted', aliasedName, true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + $customConstraints: 'DEFAULT FALSE', + defaultValue: const CustomExpression('FALSE')); + late final GeneratedColumn owner = GeneratedColumn( + 'owner', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL REFERENCES users (id)'); + @override + List get $columns => [id, title, deleted, owner]; + @override + String get aliasedName => _alias ?? 'groups'; + @override + String get actualTableName => 'groups'; + @override + Set get $primaryKey => {id}; + @override + GroupsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return GroupsData( + id: attachedDatabase.options.types + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + title: attachedDatabase.options.types + .read(DriftSqlType.string, data['${effectivePrefix}title'])!, + deleted: attachedDatabase.options.types + .read(DriftSqlType.bool, data['${effectivePrefix}deleted']), + owner: attachedDatabase.options.types + .read(DriftSqlType.int, data['${effectivePrefix}owner'])!, + ); + } + + @override + Groups createAlias(String alias) { + return Groups(attachedDatabase, alias); + } + + @override + List get customConstraints => const ['PRIMARY KEY (id)']; + @override + bool get dontWriteConstraints => true; +} + +class GroupCountData extends DataClass { + final int id; + final String name; + final DateTime? birthday; + final int? nextUser; + final int groupCount; + const GroupCountData( + {required this.id, + required this.name, + this.birthday, + this.nextUser, + required this.groupCount}); + factory GroupCountData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return GroupCountData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + birthday: serializer.fromJson(json['birthday']), + nextUser: serializer.fromJson(json['nextUser']), + groupCount: serializer.fromJson(json['groupCount']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'birthday': serializer.toJson(birthday), + 'nextUser': serializer.toJson(nextUser), + 'groupCount': serializer.toJson(groupCount), + }; + } + + GroupCountData copyWith( + {int? id, + String? name, + DateTime? birthday, + int? nextUser, + int? groupCount}) => + GroupCountData( + id: id ?? this.id, + name: name ?? this.name, + birthday: birthday ?? this.birthday, + nextUser: nextUser ?? this.nextUser, + groupCount: groupCount ?? this.groupCount, + ); + @override + String toString() { + return (StringBuffer('GroupCountData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('birthday: $birthday, ') + ..write('nextUser: $nextUser, ') + ..write('groupCount: $groupCount') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, birthday, nextUser, groupCount); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is GroupCountData && + other.id == this.id && + other.name == this.name && + other.birthday == this.birthday && + other.nextUser == this.nextUser && + other.groupCount == this.groupCount); +} + +class GroupCount extends ViewInfo + implements HasResultSet { + final String? _alias; + @override + final DatabaseAtV6 attachedDatabase; + GroupCount(this.attachedDatabase, [this._alias]); + @override + List get $columns => + [id, name, birthday, 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 data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return GroupCountData( + id: attachedDatabase.options.types + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + name: attachedDatabase.options.types + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + birthday: attachedDatabase.options.types + .read(DriftSqlType.dateTime, data['${effectivePrefix}birthday']), + nextUser: attachedDatabase.options.types + .read(DriftSqlType.int, data['${effectivePrefix}next_user']), + groupCount: attachedDatabase.options.types + .read(DriftSqlType.int, data['${effectivePrefix}group_count'])!, + ); + } + + late final GeneratedColumn id = + GeneratedColumn('id', aliasedName, false, type: DriftSqlType.int); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string); + late final GeneratedColumn birthday = GeneratedColumn( + 'birthday', aliasedName, true, + type: DriftSqlType.dateTime); + late final GeneratedColumn nextUser = GeneratedColumn( + 'next_user', aliasedName, true, + type: DriftSqlType.int); + late final GeneratedColumn groupCount = GeneratedColumn( + 'group_count', aliasedName, false, + type: DriftSqlType.int); + @override + GroupCount createAlias(String alias) { + return GroupCount(attachedDatabase, alias); + } + + @override + Query? get query => null; + @override + Set get readTables => const {}; +} + +class DatabaseAtV6 extends GeneratedDatabase { + DatabaseAtV6(QueryExecutor e) : super(e); + DatabaseAtV6.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 get allTables => allSchemaEntities.whereType(); + @override + List get allSchemaEntities => + [users, groups, groupCount]; + @override + int get schemaVersion => 6; + @override + DriftDatabaseOptions get options => + const DriftDatabaseOptions(storeDateTimeAsText: true); +} diff --git a/examples/migrations_example/test/migration_test.dart b/examples/migrations_example/test/migration_test.dart index e9c94c0e..2127c498 100644 --- a/examples/migrations_example/test/migration_test.dart +++ b/examples/migrations_example/test/migration_test.dart @@ -98,4 +98,12 @@ void main() { .having((e) => e.groupCount, 'groupCount', 0))); await migratedDb.close(); }); + + test('upgrade from v5 to v6', () async { + final connection = await verifier.startAt(5); + final db = Database(connection); + addTearDown(db.close); + + await verifier.migrateAndValidate(db, 6); + }); }