Merge branch 'views' of github.com:westito/drift into views

This commit is contained in:
westito 2021-12-02 09:19:47 +01:00
commit 9e753e7837
5 changed files with 92 additions and 15 deletions

View File

@ -167,3 +167,66 @@ Applying a `customConstraint` will override all other constraints that would be
particular, that means that we need to also include the `NOT NULL` constraint again.
You can also add table-wide constraints by overriding the `customConstraints` getter in your table class.
## References
[Foreign key references](https://www.sqlite.org/foreignkeys.html) can be expressed
in Dart tables with the `references()` method when building a column:
```dart
class Todos extends Table {
// ...
IntColumn get category => integer().nullable().references(Categories, #id)();
}
@DataClassName("Category")
class Categories extends Table {
IntColumn get id => integer().autoIncrement()();
// and more columns...
}
```
The first parameter to `references` points to the table on which a reference should be created.
The second parameter is a [symbol](https://dart.dev/guides/language/language-tour#symbols) of the column to use for the reference.
Optionally, the `onUpdate` and `onDelete` parameters can be used to describe what
should happen when the target row gets updated or deleted.
Be aware that, in sqlite3, foreign key references aren't enabled by default.
They need to be enabled with `PRAGMA foreign_keys = ON`.
A suitable place to issue that pragma with drift is in a [post-migration callback]({{ '../Advanced Features/migrations.md#post-migration-callbacks' | pageUrl }}).
## Views
It is also possible to define [SQL views](https://www.sqlite.org/lang_createview.html)
as Dart classes.
To do so, write an abstract class extending `View`. This example declares a view reading
the amount of todo-items added to a category in the schema from [the example]({{ 'index.md' | pageUrl }}):
```dart
abstract class CategoryTodoCount extends View {
TodosTable get todos;
Categories get categories;
Expression<int> get itemCount => todos.id.count();
@override
Query as() => select([categories.description, itemCount])
.from(categories)
.join([innerJoin(todos, todos.category.equalsExp(categories.id))]);
}
```
Inside a Dart view, use
- abstract getters to declare tables that you'll read from (e.g. `TodosTable get todos`)
- `Expression` getters to add columns: (e.g. `itemCount => todos.id.count()`);
- the overridden `as` method to define the select statement backing the view
Finally, a view needs to be added to a database or accessor by including it in the
`views` parameter:
```dart
@DriftDatabase(tables: [Todos, Categories], views: [CategoryTodoCount])
class MyDatabase extends _$MyDatabase {
```

View File

@ -95,7 +95,7 @@ class DriftAccessor {
/// The tables accessed by this DAO.
final List<Type> tables;
/// The views to include in the database
/// The views to make accessible in this DAO.
final List<Type> views;
/// {@macro drift_compile_queries_param}

View File

@ -7,6 +7,8 @@ abstract class HasResultSet {
}
/// Subclasses represent a table in a database generated by drift.
///
/// For more information on how to write tables, see [the documentation](https://drift.simonbinder.eu/docs/getting-started/advanced_dart_tables/)
abstract class Table extends HasResultSet {
/// Defines a table to be used with drift.
const Table();
@ -119,19 +121,41 @@ abstract class Table extends HasResultSet {
}
/// Subclasses represent a view in a database generated by drift.
///
/// For more information on how to define views in Dart, see
/// [the documentation](https://drift.simonbinder.eu/docs/getting-started/advanced_dart_tables/#views)
abstract class View extends HasResultSet {
/// Defines a view to be used with drift.
const View();
/// The select method can be used in [as] to define the select query backing
/// this view.
///
/// The select statement should select all columns defined on this view.
@protected
View select(List<Expression> columns) => _isGenerated();
/// This method should be called on [select] to define the main table of this
/// view:
///
/// ```dart
/// abstract class CategoryTodoCount extends View {
/// TodosTable get todos;
/// Categories get categories;
///
/// Expression<int> get itemCount => todos.id.count();
///
/// @override
/// Query as() => select([categories.description, itemCount])
/// .from(categories)
/// .join([innerJoin(todos, todos.category.equalsExp(categories.id))]);
/// }
/// ```
@protected
SimpleSelectStatement from(Table table) => _isGenerated();
///
/// This method is overridden by Dart-defined views to declare the right
/// query to run.
@visibleForOverriding
Query as();
}
@ -210,13 +234,3 @@ class DriftView {
/// Customize view name and data class name
const DriftView({this.name, this.dataClassName});
}
///
@Target({TargetKind.getter})
class Reference {
///
final Type type;
///
const Reference(this.type);
}

View File

@ -9,7 +9,7 @@ part of '../query_builder.dart';
///
/// [sqlite-docs]: https://www.sqlite.org/lang_createview.html
/// [sql-tut]: https://www.sqlitetutorial.net/sqlite-create-view/
abstract class ViewInfo<Self extends HasResultSet, Row>
abstract class ViewInfo<Self extends View, Row>
implements ResultSetImplementation<Self, Row> {
@override
String get entityName;
@ -17,6 +17,6 @@ abstract class ViewInfo<Self extends HasResultSet, Row>
/// The `CREATE VIEW` sql statement that can be used to create this view.
String? get createViewStmt;
/// Predefined query from View.as()
/// Predefined query from `View.as()`
Query? get query;
}

View File

@ -25,7 +25,7 @@ dependencies:
io: ^1.0.3
# Moor-specific analysis and apis
drift: ^1.1.0-dev
drift: '>=1.1.0-dev <1.2.0'
sqlite3: '>=0.1.6 <2.0.0'
sqlparser: ^0.18.0