Make `generate_connect_constructor` the default

This commit is contained in:
Simon Binder 2023-01-28 16:14:27 +01:00
parent bff8d6c6a1
commit 83fad8426e
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
12 changed files with 41 additions and 49 deletions

View File

@ -48,13 +48,15 @@ At the moment, drift supports these options:
is based on the table name (e.g. a `@DataClassName('Users') class UsersTable extends Table` would generate
a `UsersTableCompanion`). With this option, the name is based on the data class (so `UsersCompanion` in
this case).
* `use_column_name_as_json_key_when_defined_in_moor_file` (defaults to `true`): When serializing columns declared inside a
* `use_column_name_as_json_key_when_defined_in_moor_file` (defaults to `true`): When serializing columns declared inside a
`.moor` (or `.drift`) file from and to json, use their sql name instead of the generated Dart getter name
(so a column named `user_name` would also use `user_name` as a json key instead of `userName`).
You can always override the json key by using a `JSON KEY` column constraint
(e.g. `user_name VARCHAR NOT NULL JSON KEY userName`).
* `generate_connect_constructor`: Generate necessary code to support the [isolate runtime]({{ "isolates.md" | pageUrl }}).
This is a build option because isolates are still experimental. This will be the default option eventually.
* `generate_connect_constructor`: Generates a named `connect()` constructor on database classes
that takes a `DatabaseConnection` instead of a `QueryExecutor` - this allows sharing stream queries
between two drift database instances, which can be helpful for some [isolate setups]({{ "isolates.md" | pageUrl }}).
The option is enabled by default.
* `data_class_to_companions` (defaults to `true`): Controls whether drift will write the `toCompanion` method in generated
data classes.
* `mutable_classes` (defaults to `false`): The fields generated in generated data, companion and result set classes are final

View File

@ -45,7 +45,7 @@ replacement for the `NativeDatabase` you've been using before:
{% include "blocks/snippet" snippets = snippets name = 'simple' %}
In the common case where you only need a isolate for performance reasons, this
is as simple as it gets.
is everything you need to do to run queries in a background isolate.
The rest of this article explains a more complex setup giving you full control
over the internal components making up a drift isolate. This is useful for
advanced use cases, including:
@ -60,29 +60,26 @@ the complicated bits are hidden behind a simple method.
## Preparations
To use the isolate api, first enable the appropriate [build option]({{ "builder_options.md" | pageUrl }}) by
creating a file called `build.yaml` in your project root, next to your `pubspec.yaml`. It should have the following
content:
```yaml
targets:
$default:
builders:
drift_dev:
options:
generate_connect_constructor: true
```
When a drift database is opened multiple times, the two instances need to
synchronize query streams, so that updates made in one instance are reflected
in queries watched by the other.
Next, re-run the build. You can now add another constructor to the generated database class:
By default, drift databases are created from a `QueryExecutor` - an interface
responsible for running the SQL statements generated by higher-level drift APIs.
To share both the underlying database and a drift-specific mechanism for
streams, you can instead use a `DatabaseConnection` instance. For that, you need
to use the generated `connect()` constructor in your database class:
{% include "blocks/snippet" snippets = snippets name = 'database' %}
This setup is unfortunately necessary for backwards compatibility. A
`DatabaseConnection` and the `connect` constructor make it possible to share
query streams between isolates, the default constructor can't do this. In a
future drift reelase, this option will no longer be necessary.
Having a second constructor taking a `DatabaseConnection` is necessary for
backwards compatibility since the default constructor only takes a
`QueryExecutor` which is insufficient to synchronize streams.
If you only want to open your database with a `DatabaseConnection`, you can
remove the default constructor though.
After adding the `connect` constructor, you can launch a drift isolate to
connect to:
After adding the new constructor, you can create instances of your database
that will transparently run queries on a background isolate:
## Using drift in a background isolate {#using-moor-in-a-background-isolate}
@ -102,11 +99,12 @@ Internally, drift will connect when the first query is sent to the database.
### Initialization on the main thread
At the moment, Flutter's platform channels are [not available on background isolates](https://github.com/flutter/flutter/issues/13937).
If you want to use functions like `getApplicationDocumentsDirectory` from `path_provider` to
construct the database's path, we'll have to use some tricks to avoid using platforms channels.
Here, we're going to start the isolate running the database manually. This allows us to pass additional
data that we calculated on the main thread.
Before Flutter 3.7, platforms channels weren't [available on background isolates](https://github.com/flutter/flutter/issues/13937).
So, if functions like `getApplicationDocumentsDirectory` from `path_provider`
are used to construct the path to the database, some tricks were necessary.
This section describes a workaround to start the isolate running the database
manually. This allows passing additional data that can be computed on the main
isolate, using platform channels.
{% include "blocks/snippet" snippets = snippets name = 'initialization' %}

View File

@ -369,12 +369,12 @@ void main() {
In general, a test looks like this:
- Use `verifier.startAt()` to obtain a [connection](https://pub.dev/documentation/moor/latest/moor/DatabaseConnection-class.html)
1. Use `verifier.startAt()` to obtain a [connection](https://drift.simonbinder.eu/api/drift/databaseconnection-class)
to a database with an initial schema.
This database contains all your tables, indices and triggers from that version, created by using `Migrator.createAll`.
- Create your application database (you can enable the [`generate_connect_constructor`]({{ "builder_options.md" | pageUrl }}) to use
a `DatabaseConnection` directly)
- Call `verifier.migrateAndValidate(db, version)`. This will initiate a migration towards the target version (here, `2`).
2. Create your application database with that connection - you can forward the `DatabaseConnection` to the
`GeneratedDatabase.connect()` constructor on the parent class for this.
3. Call `verifier.migrateAndValidate(db, version)`. This will initiate a migration towards the target version (here, `2`).
Unlike the database created by `startAt`, this uses the migration logic you wrote for your database.
`migrateAndValidate` will extract all `CREATE` statement from the `sqlite_schema` table and semantically compare them.

View File

@ -194,8 +194,7 @@ DatabaseConnection connectToWorker() {
}
```
You can pass that `DatabaseConnection` to your database by enabling the
`generate_connect_constructor` build option.
You can then open a drift database with that connection.
For more information on the `DatabaseConnection` class, see the documentation on
[isolates]({{ "../Advanced Features/isolates.md" | pageUrl }}).

View File

@ -15,7 +15,6 @@ targets:
options:
override_hash_and_equals_in_result_sets: true
use_column_name_as_json_key_when_defined_in_moor_file: true
generate_connect_constructor: true
write_from_json_string_constructor: true
raw_result_set_data: true
named_parameters: true
@ -38,7 +37,6 @@ targets:
# Dart doesn't support YAML merge tags yet, https://github.com/dart-lang/yaml/issues/121
override_hash_and_equals_in_result_sets: true
use_column_name_as_json_key_when_defined_in_moor_file: true
generate_connect_constructor: true
write_from_json_string_constructor: true
raw_result_set_data: true
named_parameters: true

View File

@ -4,6 +4,7 @@
- Support `MAPPED BY` for individual columns in queries or in views defined with SQL.
- Consistently interpret `CAST (x AS DATETIME)` and `CAST(x AS TEXT)` in drift files.
- Support a `CAST` to an enum type in drift types.
- The `generate_connect_constructor` option is now enabled by default.
- Support two different queries using `LIST()` columns having the same result class name.
- Fix table classes not extending defining Dart classes with modular generation.
- Fix `@UseDataClass` with `extending` not working with modular generation.

View File

@ -45,9 +45,12 @@ class DriftOptions {
defaultValue: true)
final bool useColumnNameAsJsonKeyWhenDefinedInMoorFile;
/// Generate a `connect` constructor in database superclasses. This is
/// required to run databases in a background isolate.
@JsonKey(name: 'generate_connect_constructor', defaultValue: false)
/// Generate a `connect` constructor in database superclasses.
///
/// This makes drift generate a constructor for database classes that takes a
/// `DatabaseConnection` instead of just a `QueryExecutor` - meaning that
/// stream queries can also be shared across multiple database instances.
@JsonKey(name: 'generate_connect_constructor', defaultValue: true)
final bool generateConnectConstructor;
@JsonKey(name: 'sqlite_modules', defaultValue: [])
@ -104,7 +107,7 @@ class DriftOptions {
this.skipVerificationCode = false,
this.useDataClassNameForCompanions = false,
this.useColumnNameAsJsonKeyWhenDefinedInMoorFile = true,
this.generateConnectConstructor = false,
this.generateConnectConstructor = true,
this.dataClassToCompanions = true,
this.generateMutableClasses = false,
this.rawResultSetData = false,
@ -180,9 +183,6 @@ class DriftOptions {
bool hasModule(SqlModule module) => effectiveModules.contains(module);
/// Checks whether a deprecated option is enabled.
///
/// At this time, all deprecated options have been removed, meaning that this
/// getter always returns `false`.
bool get enabledDeprecatedOption => false;
SqlDialect get effectiveDialect => dialect?.dialect ?? SqlDialect.sqlite;

View File

@ -49,7 +49,7 @@ DriftOptions _$DriftOptionsFromJson(Map json) => $checkedCreate(
'use_column_name_as_json_key_when_defined_in_moor_file',
(v) => v as bool? ?? true),
generateConnectConstructor: $checkedConvert(
'generate_connect_constructor', (v) => v as bool? ?? false),
'generate_connect_constructor', (v) => v as bool? ?? true),
dataClassToCompanions: $checkedConvert(
'data_class_to_companions', (v) => v as bool? ?? true),
generateMutableClasses:

View File

@ -25,9 +25,6 @@ targets:
version: "3.38"
modules: [fts5]
# This allows us to share a drift database across isolates (or different tabs on the web)
generate_connect_constructor: true
# Configuring this builder isn't required for most apps. In our case, we
# want to compile the web worker in `web/worker.dart` to JS and we use the
# build system for that.

View File

@ -3,7 +3,6 @@ targets:
builders:
drift_dev:
options:
generate_connect_constructor: true
store_date_time_values_as_text: true
sql:
dialect: sqlite

View File

@ -31,7 +31,6 @@ targets:
builders:
drift_dev:
options:
generate_connect_constructor: true
named_parameters: true
build_web_compilers:entrypoint:
generate_for:

View File

@ -5,7 +5,6 @@ targets:
options:
override_hash_and_equals_in_result_sets: true
use_column_name_as_json_key_when_defined_in_moor_file: true
generate_connect_constructor: true
write_from_json_string_constructor: true
raw_result_set_data: false
named_parameters: false