Skip to content

Commit e9243d1

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 03a627c commit e9243d1

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.
@@ -84,12 +86,13 @@ class AppDatabase extends _$AppDatabase {
8486
}
8587
assert(1 <= from && from <= to && to <= schemaVersion);
8688

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

9598
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
@@ -378,6 +378,7 @@ run_l10n() {
378378

379379
run_drift() {
380380
local schema_dir=test/model/schemas/
381+
local migration_helper_path=lib/model/schema_versions.g.dart
381382

382383
# Omitted from this check:
383384
# pubspec.{yaml,lock} tools/check
@@ -386,15 +387,21 @@ run_drift() {
386387

387388
check_no_uncommitted_or_untracked "${schema_dir}" \
388389
|| return
390+
check_no_uncommitted_or_untracked "${migration_helper_path}" \
391+
|| return
389392

390393
dart run drift_dev schema dump \
391394
lib/model/database.dart "${schema_dir}" \
392395
|| return
393396
dart run drift_dev schema generate --data-classes --companions \
394397
"${schema_dir}" "${schema_dir}" \
395398
|| return
399+
dart run drift_dev schema steps \
400+
"${schema_dir}" "${migration_helper_path}" \
401+
|| return
396402

397403
check_no_changes "schema updates" "${schema_dir}"
404+
check_no_changes "migration helper updates" "${migration_helper_path}"
398405
}
399406

400407
filter_flutter_pub_run_output() {

0 commit comments

Comments
 (0)