Skip to content

Commit

Permalink
Support custom directory in drift_flutter
Browse files Browse the repository at this point in the history
Closes #3372
Closes #3374
  • Loading branch information
simolus3 committed Dec 29, 2024
1 parent 2e40917 commit ca9b769
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 7 deletions.
12 changes: 9 additions & 3 deletions docs/lib/snippets/setup/database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:drift/native.dart';
// #enddocregion sqlite3
// #docregion postgres
import 'package:drift_postgres/drift_postgres.dart';
import 'package:path_provider/path_provider.dart';
import 'package:postgres/postgres.dart' as pg;
// #enddocregion postgres

Expand Down Expand Up @@ -51,9 +52,14 @@ class AppDatabase extends _$AppDatabase {
class OpenFlutter {
// #docregion flutter
static QueryExecutor _openConnection() {
// `driftDatabase` from `package:drift_flutter` stores the database in
// `getApplicationDocumentsDirectory()`.
return driftDatabase(name: 'my_database');
return driftDatabase(
name: 'my_database',
native: DriftNativeOptions(
// By default, `driftDatabase` from `package:drift_flutter` stores the
// database files in `getApplicationDocumentsDirectory()`.
databaseDirectory: getApplicationSupportDirectory,
),
);
}
}
// #enddocregion flutter
Expand Down
2 changes: 2 additions & 0 deletions drift_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## 0.2.4-dev

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

## 0.2.3

Expand Down
24 changes: 23 additions & 1 deletion drift_flutter/lib/src/connect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,26 @@ final class DriftNativeOptions {
///
/// This function, which can be asynchronous for convenience, allows using
/// a custom database path in another directory.
///
/// At most one of [databasePath] or [databaseDirectory] may be used. Using
/// [databasePath] allows more control over the file name, while
/// [databaseDirectory] can be used to select another directory from
/// `path_provider` more easily.
final Future<String> Function()? databasePath;

/// An optional function returning either a string or a `Directory` that will
/// be used as a directory to store the database.
///
/// By default, drift will use `getApplicationDocumentsDirectory()` function
/// from `package:path_provider` as a directory an `$name.sqlite` as a file
/// name in that directory.
///
/// At most one of [databasePath] or [databaseDirectory] may be used. Using
/// [databasePath] allows more control over the file name, while
/// [databaseDirectory] can be used to select another directory from
/// `path_provider` more easily.
final Future<Object> Function()? databaseDirectory;

/// An optional callback returning a temporary directory.
///
/// For larger queries, sqlite3 might store intermediate results in memory.
Expand All @@ -88,6 +106,10 @@ final class DriftNativeOptions {
const DriftNativeOptions({
this.shareAcrossIsolates = false,
this.databasePath,
this.databaseDirectory,
this.tempDirectoryPath,
});
}) : assert(
databasePath == null || databaseDirectory == null,
'databasePath and databaseDirectory must not both be set.',
);
}
18 changes: 16 additions & 2 deletions drift_flutter/lib/src/native.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,22 @@ QueryExecutor driftDatabase({
if (native?.databasePath case final lookupPath?) {
return File(await lookupPath());
} else {
final dbFolder = await getApplicationDocumentsDirectory();
return File(p.join(dbFolder.path, '$name.sqlite'));
final resolvedDirectory = await (native?.databaseDirectory ??
getApplicationDocumentsDirectory)();

return File(p.join(
switch (resolvedDirectory) {
Directory(:final path) => path,
final String path => path,
final other => throw ArgumentError.value(
other,
'other',
'databaseDirectory on DriftNativeOptions must resolve to a '
'directory or a path as string.',
)
},
'$name.sqlite',
));
}
}

Expand Down
2 changes: 1 addition & 1 deletion drift_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: drift_flutter
description: Easily set up drift databases across platforms in Flutter apps.
version: 0.2.3
version: 0.2.4-dev
repository: https://github.com/simolus3/drift
homepage: https://drift.simonbinder.eu/
issue_tracker: https://github.com/simolus3/drift/issues
Expand Down
32 changes: 32 additions & 0 deletions drift_flutter/test/native_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:drift_flutter/src/native.dart'
show PingWithTimeout, hasConfiguredSqlite, portName;
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqlite3/sqlite3.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;

Expand All @@ -28,6 +29,7 @@ void main() {
return switch (call.method) {
'getTemporaryDirectory' => d.sandbox,
'getApplicationDocumentsDirectory' => d.path('applications'),
'getApplicationSupportDirectory' => d.path('support'),
_ => throw UnsupportedError('Unexpected path provider call: $call')
};
});
Expand Down Expand Up @@ -69,6 +71,35 @@ void main() {
await database.close();
});

test('can use custom database directory', () async {
final database = SimpleDatabase(driftDatabase(
name: 'database',
native: DriftNativeOptions(
databaseDirectory: getApplicationSupportDirectory,
),
));
await database.customSelect('SELECT 1').get();

expect(sqlite3.tempDirectory, d.sandbox);
await d.dir('support', [
d.FileDescriptor.binaryMatcher('database.sqlite', anything),
]).validate();
await database.close();
});

test('forbids passing custom directory and custom path', () async {
expect(
() => SimpleDatabase(driftDatabase(
name: 'database',
native: DriftNativeOptions(
databasePath: () async => d.path('my_dir/custom_file'),
databaseDirectory: getApplicationSupportDirectory,
),
)),
throwsAssertionError,
);
});

test('can use custom temporary directory', () async {
final database = SimpleDatabase(driftDatabase(
name: 'database',
Expand Down Expand Up @@ -147,6 +178,7 @@ void main() {
final isolate = await Isolate.spawn((_) {}, '');
isolate.kill();

await pumpEventQueue(times: 1);
expect(await isolate.pingWithTimeout(), false);
});

Expand Down

0 comments on commit ca9b769

Please sign in to comment.