Skip to content

Commit ca9b769

Browse files
committed
Support custom directory in drift_flutter
Closes #3372 Closes #3374
1 parent 2e40917 commit ca9b769

File tree

6 files changed

+83
-7
lines changed

6 files changed

+83
-7
lines changed

docs/lib/snippets/setup/database.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:drift/native.dart';
1212
// #enddocregion sqlite3
1313
// #docregion postgres
1414
import 'package:drift_postgres/drift_postgres.dart';
15+
import 'package:path_provider/path_provider.dart';
1516
import 'package:postgres/postgres.dart' as pg;
1617
// #enddocregion postgres
1718

@@ -51,9 +52,14 @@ class AppDatabase extends _$AppDatabase {
5152
class OpenFlutter {
5253
// #docregion flutter
5354
static QueryExecutor _openConnection() {
54-
// `driftDatabase` from `package:drift_flutter` stores the database in
55-
// `getApplicationDocumentsDirectory()`.
56-
return driftDatabase(name: 'my_database');
55+
return driftDatabase(
56+
name: 'my_database',
57+
native: DriftNativeOptions(
58+
// By default, `driftDatabase` from `package:drift_flutter` stores the
59+
// database files in `getApplicationDocumentsDirectory()`.
60+
databaseDirectory: getApplicationSupportDirectory,
61+
),
62+
);
5763
}
5864
}
5965
// #enddocregion flutter

drift_flutter/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
## 0.2.4-dev
22

33
- Allow providing a custom temporary directory.
4+
- Allow providing a custom database directory, making it easier to swap out the
5+
default `getApplicationDocumentsDirectory()`.
46

57
## 0.2.3
68

drift_flutter/lib/src/connect.dart

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,26 @@ final class DriftNativeOptions {
6565
///
6666
/// This function, which can be asynchronous for convenience, allows using
6767
/// a custom database path in another directory.
68+
///
69+
/// At most one of [databasePath] or [databaseDirectory] may be used. Using
70+
/// [databasePath] allows more control over the file name, while
71+
/// [databaseDirectory] can be used to select another directory from
72+
/// `path_provider` more easily.
6873
final Future<String> Function()? databasePath;
6974

75+
/// An optional function returning either a string or a `Directory` that will
76+
/// be used as a directory to store the database.
77+
///
78+
/// By default, drift will use `getApplicationDocumentsDirectory()` function
79+
/// from `package:path_provider` as a directory an `$name.sqlite` as a file
80+
/// name in that directory.
81+
///
82+
/// At most one of [databasePath] or [databaseDirectory] may be used. Using
83+
/// [databasePath] allows more control over the file name, while
84+
/// [databaseDirectory] can be used to select another directory from
85+
/// `path_provider` more easily.
86+
final Future<Object> Function()? databaseDirectory;
87+
7088
/// An optional callback returning a temporary directory.
7189
///
7290
/// For larger queries, sqlite3 might store intermediate results in memory.
@@ -88,6 +106,10 @@ final class DriftNativeOptions {
88106
const DriftNativeOptions({
89107
this.shareAcrossIsolates = false,
90108
this.databasePath,
109+
this.databaseDirectory,
91110
this.tempDirectoryPath,
92-
});
111+
}) : assert(
112+
databasePath == null || databaseDirectory == null,
113+
'databasePath and databaseDirectory must not both be set.',
114+
);
93115
}

drift_flutter/lib/src/native.dart

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,22 @@ QueryExecutor driftDatabase({
3434
if (native?.databasePath case final lookupPath?) {
3535
return File(await lookupPath());
3636
} else {
37-
final dbFolder = await getApplicationDocumentsDirectory();
38-
return File(p.join(dbFolder.path, '$name.sqlite'));
37+
final resolvedDirectory = await (native?.databaseDirectory ??
38+
getApplicationDocumentsDirectory)();
39+
40+
return File(p.join(
41+
switch (resolvedDirectory) {
42+
Directory(:final path) => path,
43+
final String path => path,
44+
final other => throw ArgumentError.value(
45+
other,
46+
'other',
47+
'databaseDirectory on DriftNativeOptions must resolve to a '
48+
'directory or a path as string.',
49+
)
50+
},
51+
'$name.sqlite',
52+
));
3953
}
4054
}
4155

drift_flutter/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: drift_flutter
22
description: Easily set up drift databases across platforms in Flutter apps.
3-
version: 0.2.3
3+
version: 0.2.4-dev
44
repository: https://github.com/simolus3/drift
55
homepage: https://drift.simonbinder.eu/
66
issue_tracker: https://github.com/simolus3/drift/issues

drift_flutter/test/native_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import 'package:drift_flutter/src/native.dart'
1414
show PingWithTimeout, hasConfiguredSqlite, portName;
1515
import 'package:flutter/services.dart';
1616
import 'package:flutter_test/flutter_test.dart';
17+
import 'package:path_provider/path_provider.dart';
1718
import 'package:sqlite3/sqlite3.dart';
1819
import 'package:test_descriptor/test_descriptor.dart' as d;
1920

@@ -28,6 +29,7 @@ void main() {
2829
return switch (call.method) {
2930
'getTemporaryDirectory' => d.sandbox,
3031
'getApplicationDocumentsDirectory' => d.path('applications'),
32+
'getApplicationSupportDirectory' => d.path('support'),
3133
_ => throw UnsupportedError('Unexpected path provider call: $call')
3234
};
3335
});
@@ -69,6 +71,35 @@ void main() {
6971
await database.close();
7072
});
7173

74+
test('can use custom database directory', () async {
75+
final database = SimpleDatabase(driftDatabase(
76+
name: 'database',
77+
native: DriftNativeOptions(
78+
databaseDirectory: getApplicationSupportDirectory,
79+
),
80+
));
81+
await database.customSelect('SELECT 1').get();
82+
83+
expect(sqlite3.tempDirectory, d.sandbox);
84+
await d.dir('support', [
85+
d.FileDescriptor.binaryMatcher('database.sqlite', anything),
86+
]).validate();
87+
await database.close();
88+
});
89+
90+
test('forbids passing custom directory and custom path', () async {
91+
expect(
92+
() => SimpleDatabase(driftDatabase(
93+
name: 'database',
94+
native: DriftNativeOptions(
95+
databasePath: () async => d.path('my_dir/custom_file'),
96+
databaseDirectory: getApplicationSupportDirectory,
97+
),
98+
)),
99+
throwsAssertionError,
100+
);
101+
});
102+
72103
test('can use custom temporary directory', () async {
73104
final database = SimpleDatabase(driftDatabase(
74105
name: 'database',
@@ -147,6 +178,7 @@ void main() {
147178
final isolate = await Isolate.spawn((_) {}, '');
148179
isolate.kill();
149180

181+
await pumpEventQueue(times: 1);
150182
expect(await isolate.pingWithTimeout(), false);
151183
});
152184

0 commit comments

Comments
 (0)