Skip to content

Commit

Permalink
Showing 50 changed files with 650 additions and 110 deletions.
5 changes: 2 additions & 3 deletions docs/lib/snippets/dart_api/select.dart
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@ import '../_shared/todo_tables.drift.dart';
class EntryWithCategory {
EntryWithCategory(this.entry, this.category);

// The classes are generated by drift for each of the tables involved in the
// join.
final TodoItem entry;
final Category? category;
}
@@ -69,8 +71,6 @@ extension SelectExamples on CanUseCommonTables {
leftOuterJoin(categories, categories.id.equalsExp(todoItems.category)),
]);

// see next section on how to parse the result
// #enddocregion joinIntro
// #docregion results
return query.watch().map((rows) {
return rows.map((row) {
@@ -81,7 +81,6 @@ extension SelectExamples on CanUseCommonTables {
}).toList();
});
// #enddocregion results
// #docregion joinIntro
}
// #enddocregion joinIntro

23 changes: 9 additions & 14 deletions docs/lib/snippets/setup/database.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
// #docregion after_generation
// #docregion before_generation
import 'package:drift/drift.dart';

// #enddocregion before_generation
// #enddocregion after_generation

// #docregion open
// These imports are necessary to open the sqlite3 database
// #docregion after_generation
// These additional imports are necessary to open the sqlite3 database
import 'dart:io';

import 'package:drift/native.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
import 'package:sqlite3/sqlite3.dart';
import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart';

// ... the TodoItems table definition stays the same
// #enddocregion open

// #docregion before_generation
part 'database.g.dart';

@@ -27,25 +25,22 @@ class TodoItems extends Table {
IntColumn get category => integer().nullable()();
}
// #enddocregion table
// #docregion open

@DriftDatabase(tables: [TodoItems])
class AppDatabase extends _$AppDatabase {
// #enddocregion open
// #enddocregion before_generation
// #enddocregion after_generation
// After generating code, this class needs to define a `schemaVersion` getter
// and a constructor telling drift where the database should be stored.
// These are described in the getting started guide: https://drift.simonbinder.eu/getting-started/#open
// #enddocregion before_generation
// #docregion open
// #docregion after_generation
AppDatabase() : super(_openConnection());

@override
int get schemaVersion => 1;
// #docregion before_generation
}
// #enddocregion before_generation, open

// #docregion open
// #enddocregion before_generation

LazyDatabase _openConnection() {
// the LazyDatabase util lets us find the right location for the file async.
@@ -70,7 +65,7 @@ LazyDatabase _openConnection() {
return NativeDatabase.createInBackground(file);
});
}
// #enddocregion open
// #enddocregion after_generation

class WidgetsFlutterBinding {
static void ensureInitialized() {}
4 changes: 2 additions & 2 deletions docs/pages/docs/Dart API/select.md
Original file line number Diff line number Diff line change
@@ -114,14 +114,14 @@ Of course, you can also join multiple tables:

{% include "blocks/snippet" snippets = snippets name = 'otherTodosInSameCategory' %}

## Parsing results
### Parsing results

Calling `get()` or `watch` on a select statement with join returns a `Future` or `Stream` of
`List<TypedResult>`, respectively. Each `TypedResult` represents a row from which data can be
read. It contains a `rawData` getter to obtain the raw columns. But more importantly, the
`readTable` method can be used to read a data class from a table.

In the example query above, we can read the todo entry and the category from each row like this:
In the example query above, we've read the todo entry and the category from each row like this:

{% include "blocks/snippet" snippets = snippets name = 'results' %}

3 changes: 3 additions & 0 deletions docs/pages/docs/Dart API/transactions.md
Original file line number Diff line number Diff line change
@@ -30,6 +30,9 @@ There are a couple of things that should be kept in mind when working with trans
on the transaction after it has been closed! This can cause data loss or runtime crashes.
Drift contains some runtime checks against this misuse and will throw an exception when a transaction
is used after being closed.
A transaction is active during all asynchronous calls made in a `transaction` block, so transactions
also can't schedule timers or other operations using the database (as those would try to use the
transaction after the main `transaction` block has completed).
2. __Different behavior of stream queries__: Inside a `transaction` callback, stream queries behave
differently. If you're creating streams inside a transaction, check the next section to learn how
they behave.
2 changes: 2 additions & 0 deletions docs/pages/docs/Generation options/index.md
Original file line number Diff line number Diff line change
@@ -179,6 +179,8 @@ We currently support the following extensions:
- `rtree`: Static analysis support for the [R*Tree](https://www.sqlite.org/rtree.html) extension.
Enabling this option is safe when using a `NativeDatabase` with `sqlite3_flutter_libs`,
which compiles sqlite3 with the R*Tree extension enabled.
- [geopoly](https://www.sqlite.org/geopoly.html), a generalization of the R*Tree module supporting more complex
polygons.
- `moor_ffi`: Enables support for functions that are only available when using a `NativeDatabase`. This contains `pow`, `sqrt` and a variety
of trigonometric functions. Details on those functions are available [here]({{ "../Platforms/vm.md#moor-only-functions" | pageUrl }}).
- `math`: Assumes that sqlite3 was compiled with [math functions](https://www.sqlite.org/lang_mathfunc.html).
6 changes: 4 additions & 2 deletions docs/pages/docs/SQL API/drift_files.md
Original file line number Diff line number Diff line change
@@ -116,8 +116,10 @@ to determine the column type based on the declared type name.
Additionally, columns that have the type name `BOOLEAN` or `DATETIME` will have
`bool` or `DateTime` as their Dart counterpart.
Booleans are stored as `INTEGER` (either `0` or `1`). Datetimes are stored as
unix timestamps (`INTEGER`) or ISO-8601 (`TEXT`) depending on a configurable
build option.
unix timestamps (`INTEGER`) or ISO-8601 (`TEXT`) [depending on a configurable build option]({{ '../Dart API/tables.md#datetime-options' | pageUrl }}).
For integers that should be represented as a `BigInt` in Dart (i.e. to have better compatibility with large numbers when compiling to JS),
define the column with the `INT64` type.

Dart enums can automatically be stored by their index by using an `ENUM()` type
referencing the Dart enum class:

11 changes: 6 additions & 5 deletions docs/pages/docs/setup.md
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ to store todo items for a todo list app.
Everything there is to know about defining tables in Dart is described on the [Dart tables]({{'Dart API/tables.md' | pageUrl}}) page.
If you prefer using SQL to define your tables, drift supports that too! You can read all about the [SQL API]({{ 'SQL API/index.md' | pageUrl }}) here.

For now, the contents of `database.dart` are:
For now, populate the contents of `database.dart` with:

{% include "blocks/snippet" snippets = snippets name = 'before_generation' %}

@@ -97,10 +97,11 @@ After running either command, the `database.g.dart` file containing the generate
class will have been generated.
You will now see errors related to missing overrides and a missing constructor. The constructor
is responsible for telling drift how to open the database. The `schemaVersion` getter is relevant
for migrations after changing the database, we can leave it at `1` for now. The database class
now looks like this:
<a name="open">
{% include "blocks/snippet" snippets = snippets name = 'open' %}
for migrations after changing the database, we can leave it at `1` for now. Update `database.dart`
so it now looks like this:

<a name="open"></a>
{% include "blocks/snippet" snippets = snippets name = 'after_generation' %}

The Android-specific workarounds are necessary because sqlite3 attempts to use `/tmp` to store
private data on unix-like systems, which is forbidden on Android. We also use this opportunity
9 changes: 8 additions & 1 deletion drift/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
## 2.17.0-dev
## 2.18.0-dev

- Add `AggregateFunctionExpression` to write custom [aggregate function](https://www.sqlite.org/lang_aggfunc.html)
invocations in the Dart query builder.
- The `json_group_array` and `jsonb_group_array` functions now contain an `orderBy`
and `filter` parameter.

## 2.17.0

- Adds `companion` entry to `DataClassName` to override the name of the
generated companion class.
2 changes: 2 additions & 0 deletions drift/build.yaml
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ targets:
modules:
- json1
- fts5
- geopoly
build_web_compilers:entrypoint:
generate_for:
- "web/drift_worker.dart"
@@ -59,3 +60,4 @@ targets:
modules:
- json1
- fts5
- geopoly
24 changes: 16 additions & 8 deletions drift/lib/extensions/geopoly.dart
Original file line number Diff line number Diff line change
@@ -8,9 +8,13 @@ import 'dart:typed_data';
import '../src/runtime/query_builder/query_builder.dart';
import '../src/runtime/types/mapping.dart';

/// The type used for the `_shape` column in virtual `GEOPOLY` tables.
///
/// This type is responsible for representing shape values in Dart. It is
/// created by drift when the `geopoly` extension is enabled and a `CREATE
/// VIRTUAL TABLE USING geopoly` table is declared in a `.drift` file.
final class GeopolyPolygonType implements CustomSqlType<GeopolyPolygon> {
///
/// Default constant constructor for the geopoly type.
const GeopolyPolygonType();

@override
@@ -43,29 +47,33 @@ final class GeopolyPolygonType implements CustomSqlType<GeopolyPolygon> {
}
}

/// In Geopoly, a polygon can be text or a blob
/// In Geopoly, a polygon can be text or a blob.
sealed class GeopolyPolygon {
const GeopolyPolygon._();

/// Creates a geopoly shape from a textual representation listing its points.
///
/// For details on the syntax for [value], see https://www.sqlite.org/geopoly.html.
const factory GeopolyPolygon.text(String value) = GeopolyPolygonString;

/// Creates a geopoly shape from the binary representation used by sqlite3.
const factory GeopolyPolygon.blob(Uint8List value) = GeopolyPolygonBlob;
}

///
/// A [GeopolyPolygon] being described as text.
final class GeopolyPolygonString extends GeopolyPolygon {
///
/// The textual description of the polygon.
final String value;

///
/// Creates a polygon from the underlying textual [value].
const GeopolyPolygonString(this.value) : super._();
}

///
/// A [GeopolyPolygon] being described as binary data.
final class GeopolyPolygonBlob extends GeopolyPolygon {
///
/// The binary description of the polygon.
final Uint8List value;

///
/// Creates a polygon from the underlying binary [value].
const GeopolyPolygonBlob(this.value) : super._();
}
18 changes: 14 additions & 4 deletions drift/lib/extensions/json1.dart
Original file line number Diff line number Diff line change
@@ -144,17 +144,27 @@ extension JsonExtensions on Expression<String> {
/// all emails in that folder.
/// This string could be turned back into a list with
/// `(json.decode(row.read(subjects)!) as List).cast<String>()`.
Expression<String> jsonGroupArray(Expression value) {
return FunctionCallExpression('json_group_array', [value]);
Expression<String> jsonGroupArray(
Expression value, {
OrderBy? orderBy,
Expression<bool>? filter,
}) {
return AggregateFunctionExpression('json_group_array', [value],
orderBy: orderBy, filter: filter);
}

/// Returns a binary representation of a JSON array containing the result of
/// evaluating [value] in each row of the current group.
///
/// See [jsonGroupArray], the variant of this function returning a textual
/// description, for more details and an example.
Expression<Uint8List> jsonbGroupArray(Expression value) {
return FunctionCallExpression('jsonb_group_array', [value]);
Expression<Uint8List> jsonbGroupArray(
Expression value, {
OrderBy? orderBy,
Expression<bool>? filter,
}) {
return AggregateFunctionExpression('jsonb_group_array', [value],
orderBy: orderBy, filter: filter);
}

List<Expression> _groupObjectArgs(Map<Expression<String>, Expression> values) {
2 changes: 1 addition & 1 deletion drift/lib/src/runtime/executor/helpers/engines.dart
Original file line number Diff line number Diff line change
@@ -140,7 +140,7 @@ abstract class _TransactionExecutor extends _BaseExecutor

if (_closed) {
throw StateError(
"A tranaction was used after being closed. Please check that you're "
"A transaction was used after being closed. Please check that you're "
'awaiting all database operations inside a `transaction` block.');
}
}
Loading

0 comments on commit 9c82dcd

Please sign in to comment.