Skip to content

Commit a7b1456

Browse files
committed
db: Start generating step by step migration helper
An alternative to this is `dart run drift_dev make-migrations`, which is essentially a wrapper for the `schema {dump,generate,steps}` subcommands. `make-migrations` let us manage multiple database schemas by configuring them with `build.yaml`, and it dictates the which subdirectories the generated files will be created at. Because `make-migrations` does not offer the same level of customizations to designate exactly where the output files will be, opting out from it for now. We can revisit this if it starts to offer features that are not available with the subcommands, or that we find the need for managing multiple databases. See also: https://drift.simonbinder.eu/migrations/step_by_step/#manual-generation Signed-off-by: Zixuan James Li <[email protected]>
1 parent d17cb24 commit a7b1456

File tree

3 files changed

+128
-6
lines changed

3 files changed

+128
-6
lines changed

lib/model/database.dart

+9-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import 'package:drift/drift.dart';
22
import 'package:drift/remote.dart';
33
import 'package:sqlite3/common.dart';
44

5+
import 'schema_versions.g.dart';
6+
57
part 'database.g.dart';
68

79
/// The table of [Account] records in the app's database.
@@ -82,12 +84,13 @@ class AppDatabase extends _$AppDatabase {
8284
}
8385
assert(1 <= from && from <= to && to <= schemaVersion);
8486

85-
if (from < 2 && 2 <= to) {
86-
await m.addColumn(accounts, accounts.ackedPushToken);
87-
}
88-
// New migrations go here.
89-
}
90-
);
87+
await m.runMigrationSteps(from: from, to: to,
88+
steps: migrationSteps(
89+
from1To2: (m, schema) async {
90+
await m.addColumn(schema.accounts, schema.accounts.ackedPushToken);
91+
},
92+
));
93+
});
9194
}
9295

9396
Future<int> createAccount(AccountsCompanion values) async {

lib/model/schema_versions.g.dart

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// dart format width=80
2+
import 'package:drift/internal/versioned_schema.dart' as i0;
3+
import 'package:drift/drift.dart' as i1;
4+
import 'package:drift/drift.dart'; // ignore_for_file: type=lint,unused_import
5+
6+
// GENERATED BY drift_dev, DO NOT MODIFY.
7+
final class Schema2 extends i0.VersionedSchema {
8+
Schema2({required super.database}) : super(version: 2);
9+
@override
10+
late final List<i1.DatabaseSchemaEntity> entities = [
11+
accounts,
12+
];
13+
late final Shape0 accounts = Shape0(
14+
source: i0.VersionedTable(
15+
entityName: 'accounts',
16+
withoutRowId: false,
17+
isStrict: false,
18+
tableConstraints: [
19+
'UNIQUE(realm_url, user_id)',
20+
'UNIQUE(realm_url, email)',
21+
],
22+
columns: [
23+
_column_0,
24+
_column_1,
25+
_column_2,
26+
_column_3,
27+
_column_4,
28+
_column_5,
29+
_column_6,
30+
_column_7,
31+
_column_8,
32+
],
33+
attachedDatabase: database,
34+
),
35+
alias: null);
36+
}
37+
38+
class Shape0 extends i0.VersionedTable {
39+
Shape0({required super.source, required super.alias}) : super.aliased();
40+
i1.GeneratedColumn<int> get id =>
41+
columnsByName['id']! as i1.GeneratedColumn<int>;
42+
i1.GeneratedColumn<String> get realmUrl =>
43+
columnsByName['realm_url']! as i1.GeneratedColumn<String>;
44+
i1.GeneratedColumn<int> get userId =>
45+
columnsByName['user_id']! as i1.GeneratedColumn<int>;
46+
i1.GeneratedColumn<String> get email =>
47+
columnsByName['email']! as i1.GeneratedColumn<String>;
48+
i1.GeneratedColumn<String> get apiKey =>
49+
columnsByName['api_key']! as i1.GeneratedColumn<String>;
50+
i1.GeneratedColumn<String> get zulipVersion =>
51+
columnsByName['zulip_version']! as i1.GeneratedColumn<String>;
52+
i1.GeneratedColumn<String> get zulipMergeBase =>
53+
columnsByName['zulip_merge_base']! as i1.GeneratedColumn<String>;
54+
i1.GeneratedColumn<int> get zulipFeatureLevel =>
55+
columnsByName['zulip_feature_level']! as i1.GeneratedColumn<int>;
56+
i1.GeneratedColumn<String> get ackedPushToken =>
57+
columnsByName['acked_push_token']! as i1.GeneratedColumn<String>;
58+
}
59+
60+
i1.GeneratedColumn<int> _column_0(String aliasedName) =>
61+
i1.GeneratedColumn<int>('id', aliasedName, false,
62+
hasAutoIncrement: true,
63+
type: i1.DriftSqlType.int,
64+
defaultConstraints:
65+
i1.GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
66+
i1.GeneratedColumn<String> _column_1(String aliasedName) =>
67+
i1.GeneratedColumn<String>('realm_url', aliasedName, false,
68+
type: i1.DriftSqlType.string);
69+
i1.GeneratedColumn<int> _column_2(String aliasedName) =>
70+
i1.GeneratedColumn<int>('user_id', aliasedName, false,
71+
type: i1.DriftSqlType.int);
72+
i1.GeneratedColumn<String> _column_3(String aliasedName) =>
73+
i1.GeneratedColumn<String>('email', aliasedName, false,
74+
type: i1.DriftSqlType.string);
75+
i1.GeneratedColumn<String> _column_4(String aliasedName) =>
76+
i1.GeneratedColumn<String>('api_key', aliasedName, false,
77+
type: i1.DriftSqlType.string);
78+
i1.GeneratedColumn<String> _column_5(String aliasedName) =>
79+
i1.GeneratedColumn<String>('zulip_version', aliasedName, false,
80+
type: i1.DriftSqlType.string);
81+
i1.GeneratedColumn<String> _column_6(String aliasedName) =>
82+
i1.GeneratedColumn<String>('zulip_merge_base', aliasedName, true,
83+
type: i1.DriftSqlType.string);
84+
i1.GeneratedColumn<int> _column_7(String aliasedName) =>
85+
i1.GeneratedColumn<int>('zulip_feature_level', aliasedName, false,
86+
type: i1.DriftSqlType.int);
87+
i1.GeneratedColumn<String> _column_8(String aliasedName) =>
88+
i1.GeneratedColumn<String>('acked_push_token', aliasedName, true,
89+
type: i1.DriftSqlType.string);
90+
i0.MigrationStepWithVersion migrationSteps({
91+
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
92+
}) {
93+
return (currentVersion, database) async {
94+
switch (currentVersion) {
95+
case 1:
96+
final schema = Schema2(database: database);
97+
final migrator = i1.Migrator(database, schema);
98+
await from1To2(migrator, schema);
99+
return 2;
100+
default:
101+
throw ArgumentError.value('Unknown migration from $currentVersion');
102+
}
103+
};
104+
}
105+
106+
i1.OnUpgrade stepByStep({
107+
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
108+
}) =>
109+
i0.VersionedSchema.stepByStepHelper(
110+
step: migrationSteps(
111+
from1To2: from1To2,
112+
));

tools/check

+7
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ run_l10n() {
375375

376376
run_drift() {
377377
local schema_dir=test/model/schemas/
378+
local migration_helper_path=lib/model/schema_versions.g.dart
378379

379380
# Omitted from this check:
380381
# pubspec.{yaml,lock} tools/check
@@ -383,15 +384,21 @@ run_drift() {
383384

384385
check_no_uncommitted_or_untracked "${schema_dir}" \
385386
|| return
387+
check_no_uncommitted_or_untracked "${migration_helper_path}" \
388+
|| return
386389

387390
dart run drift_dev schema dump \
388391
lib/model/database.dart "${schema_dir}" \
389392
|| return
390393
dart run drift_dev schema generate --data-classes --companions \
391394
"${schema_dir}" "${schema_dir}" \
392395
|| return
396+
dart run drift_dev schema steps \
397+
"${schema_dir}" "${migration_helper_path}" \
398+
|| return
393399

394400
check_no_changes "schema updates" "${schema_dir}"
401+
check_no_changes "migration helper updates" "${migration_helper_path}"
395402
}
396403

397404
filter_flutter_pub_run_output() {

0 commit comments

Comments
 (0)