mirror of https://github.com/AMT-Cheif/drift.git
Update docs for Dart components in SQL
Scopes components are enabled by default, so the warning is no longer necessary.
This commit is contained in:
parent
48e7785491
commit
2c63c1a64e
|
@ -24,28 +24,57 @@ builders:
|
||||||
release: true
|
release: true
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
# We run drift and other builders first, syntax higlighting is more
|
prepare:
|
||||||
# accurate if the generated classes exist.
|
auto_apply_builders: false
|
||||||
source_gen:
|
builders:
|
||||||
|
":versions":
|
||||||
|
enabled: true
|
||||||
|
drift_dev:preparing_builder:
|
||||||
|
enabled: true
|
||||||
|
sources:
|
||||||
|
- "$package$"
|
||||||
|
- "lib/versions.json"
|
||||||
|
- "lib/snippets/**"
|
||||||
|
- "tool/write_versions.dart"
|
||||||
|
- "tool/snippets.dart"
|
||||||
|
- "test/generated/**"
|
||||||
|
|
||||||
|
codegen:
|
||||||
|
dependencies: [":prepare"]
|
||||||
auto_apply_builders: false
|
auto_apply_builders: false
|
||||||
builders:
|
builders:
|
||||||
drift_dev:preparing_builder:
|
drift_dev:preparing_builder:
|
||||||
|
enabled: false # Runs in prepare target
|
||||||
|
|
||||||
|
# Modular drift generation, suitable for standalone snippets that aren't part of a database
|
||||||
|
drift_dev:analyzer:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
options: &options
|
||||||
|
generate_connect_constructor: true
|
||||||
|
generate_for:
|
||||||
|
include: &modular
|
||||||
|
- "lib/snippets/modular/**"
|
||||||
|
drift_dev:modular:
|
||||||
|
enabled: true
|
||||||
|
options: *options
|
||||||
|
generate_for:
|
||||||
|
include: *modular
|
||||||
|
|
||||||
|
# Non-modular drift generation. Used for some "getting started" e2e examples.
|
||||||
drift_dev:drift_dev:
|
drift_dev:drift_dev:
|
||||||
enabled: true
|
enabled: true
|
||||||
options:
|
options: *options
|
||||||
generate_connect_constructor: true
|
generate_for:
|
||||||
|
exclude: *modular
|
||||||
json_serializable:
|
json_serializable:
|
||||||
enabled: true
|
enabled: true
|
||||||
sources:
|
sources:
|
||||||
- lib/**
|
- lib/**
|
||||||
- test/generated/**
|
- test/generated/**
|
||||||
|
|
||||||
prepare:
|
syntax_highlighting:
|
||||||
dependencies: [":source_gen"]
|
dependencies: [":codegen"]
|
||||||
builders:
|
builders:
|
||||||
":versions":
|
|
||||||
enabled: true
|
|
||||||
":code_snippets":
|
":code_snippets":
|
||||||
enabled: true
|
enabled: true
|
||||||
generate_for:
|
generate_for:
|
||||||
|
@ -58,13 +87,11 @@ targets:
|
||||||
auto_apply_builders: false
|
auto_apply_builders: false
|
||||||
sources:
|
sources:
|
||||||
- "$package$"
|
- "$package$"
|
||||||
- "lib/versions.json"
|
|
||||||
- "lib/snippets/**"
|
- "lib/snippets/**"
|
||||||
- "tool/write_versions.dart"
|
|
||||||
- "tool/snippets.dart"
|
- "tool/snippets.dart"
|
||||||
|
|
||||||
$default:
|
$default:
|
||||||
dependencies: [":prepare"]
|
dependencies: [":codegen", ":syntax_highlighting"]
|
||||||
builders:
|
builders:
|
||||||
built_site:
|
built_site:
|
||||||
release_options:
|
release_options:
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
|
||||||
|
import 'example.drift.dart';
|
||||||
|
|
||||||
|
class DartExample extends ExampleDrift {
|
||||||
|
DartExample(GeneratedDatabase attachedDatabase) : super(attachedDatabase);
|
||||||
|
|
||||||
|
// #docregion watchInCategory
|
||||||
|
Stream<List<Todo>> watchInCategory(int category) {
|
||||||
|
return filterTodos((todos) => todos.category.equals(category)).watch();
|
||||||
|
}
|
||||||
|
// #enddocregion watchInCategory
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
CREATE TABLE todos (
|
||||||
|
id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
category INTEGER REFERENCES categories(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE categories (
|
||||||
|
id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
description TEXT NOT NULL
|
||||||
|
) AS Category;
|
||||||
|
|
||||||
|
-- #docregion filterTodos
|
||||||
|
filterTodos: SELECT * FROM todos WHERE $predicate;
|
||||||
|
-- #enddocregion filterTodos
|
||||||
|
-- #docregion getTodos
|
||||||
|
getTodos ($predicate = TRUE): SELECT * FROM todos WHERE $predicate;
|
||||||
|
-- #enddocregion getTodos
|
|
@ -0,0 +1,474 @@
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
import 'package:drift/drift.dart' as i0;
|
||||||
|
import 'package:drift_docs/snippets/modular/drift/example.drift.dart' as i1;
|
||||||
|
import 'package:drift/internal/modular.dart' as i2;
|
||||||
|
|
||||||
|
class Todos extends i0.Table with i0.TableInfo<Todos, i1.Todo> {
|
||||||
|
@override
|
||||||
|
final i0.GeneratedDatabase attachedDatabase;
|
||||||
|
final String? _alias;
|
||||||
|
Todos(this.attachedDatabase, [this._alias]);
|
||||||
|
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
|
||||||
|
late final i0.GeneratedColumn<int> id = i0.GeneratedColumn<int>(
|
||||||
|
'id', aliasedName, false,
|
||||||
|
hasAutoIncrement: true,
|
||||||
|
type: i0.DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
$customConstraints: 'NOT NULL PRIMARY KEY AUTOINCREMENT');
|
||||||
|
static const i0.VerificationMeta _titleMeta =
|
||||||
|
const i0.VerificationMeta('title');
|
||||||
|
late final i0.GeneratedColumn<String> title = i0.GeneratedColumn<String>(
|
||||||
|
'title', aliasedName, false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
$customConstraints: 'NOT NULL');
|
||||||
|
static const i0.VerificationMeta _contentMeta =
|
||||||
|
const i0.VerificationMeta('content');
|
||||||
|
late final i0.GeneratedColumn<String> content = i0.GeneratedColumn<String>(
|
||||||
|
'content', aliasedName, false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
$customConstraints: 'NOT NULL');
|
||||||
|
static const i0.VerificationMeta _categoryMeta =
|
||||||
|
const i0.VerificationMeta('category');
|
||||||
|
late final i0.GeneratedColumn<int> category = i0.GeneratedColumn<int>(
|
||||||
|
'category', aliasedName, true,
|
||||||
|
type: i0.DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
$customConstraints: 'REFERENCES categories(id)');
|
||||||
|
@override
|
||||||
|
List<i0.GeneratedColumn> get $columns => [id, title, content, category];
|
||||||
|
@override
|
||||||
|
String get aliasedName => _alias ?? 'todos';
|
||||||
|
@override
|
||||||
|
String get actualTableName => 'todos';
|
||||||
|
@override
|
||||||
|
i0.VerificationContext validateIntegrity(i0.Insertable<i1.Todo> instance,
|
||||||
|
{bool isInserting = false}) {
|
||||||
|
final context = i0.VerificationContext();
|
||||||
|
final data = instance.toColumns(true);
|
||||||
|
if (data.containsKey('id')) {
|
||||||
|
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||||
|
}
|
||||||
|
if (data.containsKey('title')) {
|
||||||
|
context.handle(
|
||||||
|
_titleMeta, title.isAcceptableOrUnknown(data['title']!, _titleMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_titleMeta);
|
||||||
|
}
|
||||||
|
if (data.containsKey('content')) {
|
||||||
|
context.handle(_contentMeta,
|
||||||
|
content.isAcceptableOrUnknown(data['content']!, _contentMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_contentMeta);
|
||||||
|
}
|
||||||
|
if (data.containsKey('category')) {
|
||||||
|
context.handle(_categoryMeta,
|
||||||
|
category.isAcceptableOrUnknown(data['category']!, _categoryMeta));
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<i0.GeneratedColumn> get $primaryKey => {id};
|
||||||
|
@override
|
||||||
|
i1.Todo map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
|
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||||
|
return i1.Todo(
|
||||||
|
id: attachedDatabase.typeMapping
|
||||||
|
.read(i0.DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||||
|
title: attachedDatabase.typeMapping
|
||||||
|
.read(i0.DriftSqlType.string, data['${effectivePrefix}title'])!,
|
||||||
|
content: attachedDatabase.typeMapping
|
||||||
|
.read(i0.DriftSqlType.string, data['${effectivePrefix}content'])!,
|
||||||
|
category: attachedDatabase.typeMapping
|
||||||
|
.read(i0.DriftSqlType.int, data['${effectivePrefix}category']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Todos createAlias(String alias) {
|
||||||
|
return Todos(attachedDatabase, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get dontWriteConstraints => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Todo extends i0.DataClass implements i0.Insertable<i1.Todo> {
|
||||||
|
final int id;
|
||||||
|
final String title;
|
||||||
|
final String content;
|
||||||
|
final int? category;
|
||||||
|
const Todo(
|
||||||
|
{required this.id,
|
||||||
|
required this.title,
|
||||||
|
required this.content,
|
||||||
|
this.category});
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
map['id'] = i0.Variable<int>(id);
|
||||||
|
map['title'] = i0.Variable<String>(title);
|
||||||
|
map['content'] = i0.Variable<String>(content);
|
||||||
|
if (!nullToAbsent || category != null) {
|
||||||
|
map['category'] = i0.Variable<int>(category);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.TodosCompanion toCompanion(bool nullToAbsent) {
|
||||||
|
return i1.TodosCompanion(
|
||||||
|
id: i0.Value(id),
|
||||||
|
title: i0.Value(title),
|
||||||
|
content: i0.Value(content),
|
||||||
|
category: category == null && nullToAbsent
|
||||||
|
? const i0.Value.absent()
|
||||||
|
: i0.Value(category),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory Todo.fromJson(Map<String, dynamic> json,
|
||||||
|
{i0.ValueSerializer? serializer}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return Todo(
|
||||||
|
id: serializer.fromJson<int>(json['id']),
|
||||||
|
title: serializer.fromJson<String>(json['title']),
|
||||||
|
content: serializer.fromJson<String>(json['content']),
|
||||||
|
category: serializer.fromJson<int?>(json['category']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return <String, dynamic>{
|
||||||
|
'id': serializer.toJson<int>(id),
|
||||||
|
'title': serializer.toJson<String>(title),
|
||||||
|
'content': serializer.toJson<String>(content),
|
||||||
|
'category': serializer.toJson<int?>(category),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.Todo copyWith(
|
||||||
|
{int? id,
|
||||||
|
String? title,
|
||||||
|
String? content,
|
||||||
|
i0.Value<int?> category = const i0.Value.absent()}) =>
|
||||||
|
i1.Todo(
|
||||||
|
id: id ?? this.id,
|
||||||
|
title: title ?? this.title,
|
||||||
|
content: content ?? this.content,
|
||||||
|
category: category.present ? category.value : this.category,
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('Todo(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('title: $title, ')
|
||||||
|
..write('content: $content, ')
|
||||||
|
..write('category: $category')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(id, title, content, category);
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
(other is i1.Todo &&
|
||||||
|
other.id == this.id &&
|
||||||
|
other.title == this.title &&
|
||||||
|
other.content == this.content &&
|
||||||
|
other.category == this.category);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TodosCompanion extends i0.UpdateCompanion<i1.Todo> {
|
||||||
|
final i0.Value<int> id;
|
||||||
|
final i0.Value<String> title;
|
||||||
|
final i0.Value<String> content;
|
||||||
|
final i0.Value<int?> category;
|
||||||
|
const TodosCompanion({
|
||||||
|
this.id = const i0.Value.absent(),
|
||||||
|
this.title = const i0.Value.absent(),
|
||||||
|
this.content = const i0.Value.absent(),
|
||||||
|
this.category = const i0.Value.absent(),
|
||||||
|
});
|
||||||
|
TodosCompanion.insert({
|
||||||
|
this.id = const i0.Value.absent(),
|
||||||
|
required String title,
|
||||||
|
required String content,
|
||||||
|
this.category = const i0.Value.absent(),
|
||||||
|
}) : title = i0.Value(title),
|
||||||
|
content = i0.Value(content);
|
||||||
|
static i0.Insertable<i1.Todo> custom({
|
||||||
|
i0.Expression<int>? id,
|
||||||
|
i0.Expression<String>? title,
|
||||||
|
i0.Expression<String>? content,
|
||||||
|
i0.Expression<int>? category,
|
||||||
|
}) {
|
||||||
|
return i0.RawValuesInsertable({
|
||||||
|
if (id != null) 'id': id,
|
||||||
|
if (title != null) 'title': title,
|
||||||
|
if (content != null) 'content': content,
|
||||||
|
if (category != null) 'category': category,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.TodosCompanion copyWith(
|
||||||
|
{i0.Value<int>? id,
|
||||||
|
i0.Value<String>? title,
|
||||||
|
i0.Value<String>? content,
|
||||||
|
i0.Value<int?>? category}) {
|
||||||
|
return i1.TodosCompanion(
|
||||||
|
id: id ?? this.id,
|
||||||
|
title: title ?? this.title,
|
||||||
|
content: content ?? this.content,
|
||||||
|
category: category ?? this.category,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
if (id.present) {
|
||||||
|
map['id'] = i0.Variable<int>(id.value);
|
||||||
|
}
|
||||||
|
if (title.present) {
|
||||||
|
map['title'] = i0.Variable<String>(title.value);
|
||||||
|
}
|
||||||
|
if (content.present) {
|
||||||
|
map['content'] = i0.Variable<String>(content.value);
|
||||||
|
}
|
||||||
|
if (category.present) {
|
||||||
|
map['category'] = i0.Variable<int>(category.value);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('i1.TodosCompanion(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('title: $title, ')
|
||||||
|
..write('content: $content, ')
|
||||||
|
..write('category: $category')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Categories extends i0.Table with i0.TableInfo<Categories, i1.Category> {
|
||||||
|
@override
|
||||||
|
final i0.GeneratedDatabase attachedDatabase;
|
||||||
|
final String? _alias;
|
||||||
|
Categories(this.attachedDatabase, [this._alias]);
|
||||||
|
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
|
||||||
|
late final i0.GeneratedColumn<int> id = i0.GeneratedColumn<int>(
|
||||||
|
'id', aliasedName, false,
|
||||||
|
hasAutoIncrement: true,
|
||||||
|
type: i0.DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
$customConstraints: 'NOT NULL PRIMARY KEY AUTOINCREMENT');
|
||||||
|
static const i0.VerificationMeta _descriptionMeta =
|
||||||
|
const i0.VerificationMeta('description');
|
||||||
|
late final i0.GeneratedColumn<String> description =
|
||||||
|
i0.GeneratedColumn<String>('description', aliasedName, false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
$customConstraints: 'NOT NULL');
|
||||||
|
@override
|
||||||
|
List<i0.GeneratedColumn> get $columns => [id, description];
|
||||||
|
@override
|
||||||
|
String get aliasedName => _alias ?? 'categories';
|
||||||
|
@override
|
||||||
|
String get actualTableName => 'categories';
|
||||||
|
@override
|
||||||
|
i0.VerificationContext validateIntegrity(i0.Insertable<i1.Category> instance,
|
||||||
|
{bool isInserting = false}) {
|
||||||
|
final context = i0.VerificationContext();
|
||||||
|
final data = instance.toColumns(true);
|
||||||
|
if (data.containsKey('id')) {
|
||||||
|
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||||
|
}
|
||||||
|
if (data.containsKey('description')) {
|
||||||
|
context.handle(
|
||||||
|
_descriptionMeta,
|
||||||
|
description.isAcceptableOrUnknown(
|
||||||
|
data['description']!, _descriptionMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_descriptionMeta);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<i0.GeneratedColumn> get $primaryKey => {id};
|
||||||
|
@override
|
||||||
|
i1.Category map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
|
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||||
|
return i1.Category(
|
||||||
|
id: attachedDatabase.typeMapping
|
||||||
|
.read(i0.DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||||
|
description: attachedDatabase.typeMapping
|
||||||
|
.read(i0.DriftSqlType.string, data['${effectivePrefix}description'])!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Categories createAlias(String alias) {
|
||||||
|
return Categories(attachedDatabase, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get dontWriteConstraints => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Category extends i0.DataClass implements i0.Insertable<i1.Category> {
|
||||||
|
final int id;
|
||||||
|
final String description;
|
||||||
|
const Category({required this.id, required this.description});
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
map['id'] = i0.Variable<int>(id);
|
||||||
|
map['description'] = i0.Variable<String>(description);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.CategoriesCompanion toCompanion(bool nullToAbsent) {
|
||||||
|
return i1.CategoriesCompanion(
|
||||||
|
id: i0.Value(id),
|
||||||
|
description: i0.Value(description),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory Category.fromJson(Map<String, dynamic> json,
|
||||||
|
{i0.ValueSerializer? serializer}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return Category(
|
||||||
|
id: serializer.fromJson<int>(json['id']),
|
||||||
|
description: serializer.fromJson<String>(json['description']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return <String, dynamic>{
|
||||||
|
'id': serializer.toJson<int>(id),
|
||||||
|
'description': serializer.toJson<String>(description),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.Category copyWith({int? id, String? description}) => i1.Category(
|
||||||
|
id: id ?? this.id,
|
||||||
|
description: description ?? this.description,
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('Category(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('description: $description')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(id, description);
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
(other is i1.Category &&
|
||||||
|
other.id == this.id &&
|
||||||
|
other.description == this.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CategoriesCompanion extends i0.UpdateCompanion<i1.Category> {
|
||||||
|
final i0.Value<int> id;
|
||||||
|
final i0.Value<String> description;
|
||||||
|
const CategoriesCompanion({
|
||||||
|
this.id = const i0.Value.absent(),
|
||||||
|
this.description = const i0.Value.absent(),
|
||||||
|
});
|
||||||
|
CategoriesCompanion.insert({
|
||||||
|
this.id = const i0.Value.absent(),
|
||||||
|
required String description,
|
||||||
|
}) : description = i0.Value(description);
|
||||||
|
static i0.Insertable<i1.Category> custom({
|
||||||
|
i0.Expression<int>? id,
|
||||||
|
i0.Expression<String>? description,
|
||||||
|
}) {
|
||||||
|
return i0.RawValuesInsertable({
|
||||||
|
if (id != null) 'id': id,
|
||||||
|
if (description != null) 'description': description,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.CategoriesCompanion copyWith(
|
||||||
|
{i0.Value<int>? id, i0.Value<String>? description}) {
|
||||||
|
return i1.CategoriesCompanion(
|
||||||
|
id: id ?? this.id,
|
||||||
|
description: description ?? this.description,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
if (id.present) {
|
||||||
|
map['id'] = i0.Variable<int>(id.value);
|
||||||
|
}
|
||||||
|
if (description.present) {
|
||||||
|
map['description'] = i0.Variable<String>(description.value);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('i1.CategoriesCompanion(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('description: $description')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleDrift extends i2.ModularAccessor {
|
||||||
|
ExampleDrift(i0.GeneratedDatabase db) : super(db);
|
||||||
|
i0.Selectable<i1.Todo> filterTodos(FilterTodos$predicate predicate) {
|
||||||
|
var $arrayStartIndex = 1;
|
||||||
|
final generatedpredicate =
|
||||||
|
$write(predicate(this.todos), startIndex: $arrayStartIndex);
|
||||||
|
$arrayStartIndex += generatedpredicate.amountOfVariables;
|
||||||
|
return customSelect('SELECT * FROM todos WHERE ${generatedpredicate.sql}',
|
||||||
|
variables: [
|
||||||
|
...generatedpredicate.introducedVariables
|
||||||
|
],
|
||||||
|
readsFrom: {
|
||||||
|
todos,
|
||||||
|
...generatedpredicate.watchedTables,
|
||||||
|
}).asyncMap(todos.mapFromRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
i0.Selectable<i1.Todo> getTodos({GetTodos$predicate? predicate}) {
|
||||||
|
var $arrayStartIndex = 1;
|
||||||
|
final generatedpredicate = $write(
|
||||||
|
predicate?.call(this.todos) ?? const i0.CustomExpression('(TRUE)'),
|
||||||
|
startIndex: $arrayStartIndex);
|
||||||
|
$arrayStartIndex += generatedpredicate.amountOfVariables;
|
||||||
|
return customSelect('SELECT * FROM todos WHERE ${generatedpredicate.sql}',
|
||||||
|
variables: [
|
||||||
|
...generatedpredicate.introducedVariables
|
||||||
|
],
|
||||||
|
readsFrom: {
|
||||||
|
todos,
|
||||||
|
...generatedpredicate.watchedTables,
|
||||||
|
}).asyncMap(todos.mapFromRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.Todos get todos => this.resultSet<i1.Todos>('todos');
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef FilterTodos$predicate = i0.Expression<bool> Function(i1.Todos todos);
|
||||||
|
typedef GetTodos$predicate = i0.Expression<bool> Function(i1.Todos todos);
|
|
@ -15,6 +15,9 @@ template: layouts/docs/single
|
||||||
{% assign drift_tables = "package:drift_docs/snippets/drift_files/tables.drift.excerpt.json" | readString | json_decode %}
|
{% assign drift_tables = "package:drift_docs/snippets/drift_files/tables.drift.excerpt.json" | readString | json_decode %}
|
||||||
{% assign small = "package:drift_docs/snippets/drift_files/small_snippets.drift.excerpt.json" | readString | json_decode %}
|
{% assign small = "package:drift_docs/snippets/drift_files/small_snippets.drift.excerpt.json" | readString | json_decode %}
|
||||||
|
|
||||||
|
{% assign newDrift = "package:drift_docs/snippets/modular/drift/example.drift.excerpt.json" | readString | json_decode %}
|
||||||
|
{% assign newDart = "package:drift_docs/snippets/modular/drift/dart_example.dart.excerpt.json" | readString | json_decode %}
|
||||||
|
|
||||||
Drift files are a new feature that lets you write all your database code in SQL.
|
Drift files are a new feature that lets you write all your database code in SQL.
|
||||||
But unlike raw SQL strings you might pass to simple database clients, everything in a drift file is verified
|
But unlike raw SQL strings you might pass to simple database clients, everything in a drift file is verified
|
||||||
by drift's powerful SQL analyzer.
|
by drift's powerful SQL analyzer.
|
||||||
|
@ -291,16 +294,14 @@ would generate a column serialized as "userId" in json.
|
||||||
You can make most of both SQL and Dart with "Dart Templates", which is a
|
You can make most of both SQL and Dart with "Dart Templates", which is a
|
||||||
Dart expression that gets inlined to a query at runtime. To use them, declare a
|
Dart expression that gets inlined to a query at runtime. To use them, declare a
|
||||||
$-variable in a query:
|
$-variable in a query:
|
||||||
```sql
|
|
||||||
_filterTodos: SELECT * FROM todos WHERE $predicate;
|
{% include "blocks/snippet" snippets = newDrift name = "filterTodos" %}
|
||||||
```
|
|
||||||
Drift will generate a `Selectable<Todo> _filterTodos(Expression<bool> predicate)`
|
Drift will generate a `Selectable<Todo>` method with a `predicate` parameter that
|
||||||
method that can be used to construct dynamic filters at runtime:
|
can be used to construct dynamic filters at runtime:
|
||||||
```dart
|
|
||||||
Stream<List<Todo>> watchInCategory(int category) {
|
{% include "blocks/snippet" snippets = newDart name = "watchInCategory" %}
|
||||||
return _filterTodos(todos.category.equals(category)).watch();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
This lets you write a single SQL query and dynamically apply a predicate at runtime!
|
This lets you write a single SQL query and dynamically apply a predicate at runtime!
|
||||||
This feature works for
|
This feature works for
|
||||||
|
|
||||||
|
@ -314,46 +315,11 @@ This feature works for
|
||||||
|
|
||||||
When used as expression, you can also supply a default value in your query:
|
When used as expression, you can also supply a default value in your query:
|
||||||
|
|
||||||
```sql
|
{% include "blocks/snippet" snippets = newDrift name = "getTodos" %}
|
||||||
_filterTodos ($predicate = TRUE): SELECT * FROM todos WHERE $predicate;
|
|
||||||
```
|
|
||||||
|
|
||||||
This will make the `predicate` parameter optional in Dart. It will use the
|
This will make the `predicate` parameter optional in Dart. It will use the
|
||||||
default SQL value (here, `TRUE`) when not explicitly set.
|
default SQL value (here, `TRUE`) when not explicitly set.
|
||||||
|
|
||||||
{% block "blocks/alert" title="Using column names in Dart" color="warning" %}
|
|
||||||
If your query uses table aliases, you'll need to account for that when embedding Dart
|
|
||||||
expressions in your SQL query. Consider this for instance:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
findRoutes: SELECT r.* FROM routes r
|
|
||||||
INNER JOIN points "start" ON "start".id = r."start"
|
|
||||||
INNER JOIN points "end" ON "end".id = r."end"
|
|
||||||
WHERE $predicate
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to filter for the `start` point in Dart, you have to use
|
|
||||||
an explicit [`alias`](https://pub.dev/documentation/drift/latest/drift/DatabaseConnectionUser/alias.html):
|
|
||||||
|
|
||||||
```dart
|
|
||||||
Future<List<Route>> routesByStart(int startPointId) {
|
|
||||||
final start = alias(points, 'start');
|
|
||||||
return findRoutes(start.id.equals(startPointId));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can enable the `scoped_dart_components` [build option]({{ '../Advanced Features/builder_options.md' | pageUrl }})
|
|
||||||
and let the generator help you here.
|
|
||||||
When the option is enabled, drift would generate a `Expression<bool> Function(Routes r, Points start, Points end)` as a parameter, which
|
|
||||||
makes this a lot easier:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
Future<List<Route>> routesByStart(int startPointId) {
|
|
||||||
return findRoutes((r, start, end) => start.id.equals(startPointId));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
### Type converters
|
### Type converters
|
||||||
|
|
||||||
You can import and use [type converters]({{ "../Advanced Features/type_converters.md" | pageUrl }})
|
You can import and use [type converters]({{ "../Advanced Features/type_converters.md" | pageUrl }})
|
||||||
|
|
|
@ -14,7 +14,7 @@ dependencies:
|
||||||
version: ^0.2.2
|
version: ^0.2.2
|
||||||
code_snippets:
|
code_snippets:
|
||||||
hosted: https://simonbinder.eu
|
hosted: https://simonbinder.eu
|
||||||
version: ^0.0.8
|
version: ^0.0.11
|
||||||
# used in snippets
|
# used in snippets
|
||||||
http: ^0.13.5
|
http: ^0.13.5
|
||||||
sqlite3: ^1.7.2
|
sqlite3: ^1.7.2
|
||||||
|
|
|
@ -1,4 +1,2 @@
|
||||||
{% assign excerpt = args.name | default: '(full)' %}
|
{% assign excerpt = args.name | default: '(full)' %}
|
||||||
<pre>
|
<pre><code class="hljs">{{ args.snippets | get: excerpt }}</code></pre>
|
||||||
<code class="hljs">{{ args.snippets | get: excerpt }}</code>
|
|
||||||
</pre>
|
|
||||||
|
|
|
@ -339,7 +339,7 @@ class _DriftBuildRun {
|
||||||
);
|
);
|
||||||
writer = Writer(options, generationOptions: generationOptions);
|
writer = Writer(options, generationOptions: generationOptions);
|
||||||
} else {
|
} else {
|
||||||
final imports = LibraryInputManager();
|
final imports = LibraryInputManager(buildStep.allowedOutputs.single.uri);
|
||||||
final generationOptions = GenerationOptions(
|
final generationOptions = GenerationOptions(
|
||||||
imports: imports,
|
imports: imports,
|
||||||
isModular: true,
|
isModular: true,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:path/path.dart' show url;
|
||||||
|
|
||||||
import '../utils/string_escaper.dart';
|
import '../utils/string_escaper.dart';
|
||||||
import 'writer.dart';
|
import 'writer.dart';
|
||||||
|
|
||||||
|
@ -16,9 +18,16 @@ class LibraryInputManager extends ImportManager {
|
||||||
static final _dartCore = Uri.parse('dart:core');
|
static final _dartCore = Uri.parse('dart:core');
|
||||||
|
|
||||||
final Map<Uri, String> _importAliases = {};
|
final Map<Uri, String> _importAliases = {};
|
||||||
|
|
||||||
|
/// The uri of the file being generated.
|
||||||
|
///
|
||||||
|
/// This allows constructing relative imports for assets that aren't in
|
||||||
|
/// `lib/`.
|
||||||
|
final Uri? _outputUri;
|
||||||
|
|
||||||
TextEmitter? emitter;
|
TextEmitter? emitter;
|
||||||
|
|
||||||
LibraryInputManager();
|
LibraryInputManager([this._outputUri]);
|
||||||
|
|
||||||
void linkToWriter(Writer writer) {
|
void linkToWriter(Writer writer) {
|
||||||
emitter = writer.leaf();
|
emitter = writer.leaf();
|
||||||
|
@ -33,8 +42,20 @@ class LibraryInputManager extends ImportManager {
|
||||||
return _importAliases.putIfAbsent(definitionUri, () {
|
return _importAliases.putIfAbsent(definitionUri, () {
|
||||||
final alias = 'i${_importAliases.length}';
|
final alias = 'i${_importAliases.length}';
|
||||||
|
|
||||||
emitter?.writeln(
|
final importedScheme = definitionUri.scheme;
|
||||||
'import ${asDartLiteral(definitionUri.toString())} as $alias;');
|
String importLiteral;
|
||||||
|
|
||||||
|
if (importedScheme != 'package' &&
|
||||||
|
importedScheme != 'dart' &&
|
||||||
|
importedScheme == _outputUri?.scheme) {
|
||||||
|
// Not a package nor a dart import, use a relative import instead
|
||||||
|
importLiteral = url.relative(definitionUri.path,
|
||||||
|
from: url.dirname(_outputUri!.path));
|
||||||
|
} else {
|
||||||
|
importLiteral = definitionUri.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter?.writeln('import ${asDartLiteral(importLiteral)} as $alias;');
|
||||||
return alias;
|
return alias;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import 'package:build/build.dart';
|
||||||
|
import 'package:drift_dev/src/analysis/options.dart';
|
||||||
|
import 'package:drift_dev/src/analysis/results/results.dart';
|
||||||
|
import 'package:drift_dev/src/writer/import_manager.dart';
|
||||||
|
import 'package:drift_dev/src/writer/writer.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('LibraryInputManager', () {
|
||||||
|
final sourceUri = AssetId('a', 'example/main.dart').uri;
|
||||||
|
|
||||||
|
late LibraryInputManager imports;
|
||||||
|
late Writer writer;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
imports = LibraryInputManager(sourceUri);
|
||||||
|
final generationOptions =
|
||||||
|
GenerationOptions(imports: imports, isModular: true);
|
||||||
|
writer = Writer(const DriftOptions.defaults(),
|
||||||
|
generationOptions: generationOptions);
|
||||||
|
imports.linkToWriter(writer);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('does not generate prefix for dart:core', () {
|
||||||
|
expect(imports.prefixFor(Uri.parse('dart:core'), 'String'), isNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('writes imports', () {
|
||||||
|
expect(imports.prefixFor(AnnotatedDartCode.dartAsync, 'Future'), 'i0');
|
||||||
|
expect(imports.prefixFor(AnnotatedDartCode.drift, 'GeneratedDatabase'),
|
||||||
|
'i1');
|
||||||
|
expect(imports.prefixFor(AnnotatedDartCode.dartAsync, 'Stream'), 'i0');
|
||||||
|
|
||||||
|
expect(writer.writeGenerated(), '''
|
||||||
|
import 'dart:async' as i0;
|
||||||
|
import 'package:drift/drift.dart' as i1;
|
||||||
|
''');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can write imports for files outside of lib', () {
|
||||||
|
final uri = AssetId('a', 'example/imported.dart').uri;
|
||||||
|
expect(imports.prefixFor(uri, 'Test'), 'i0');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
writer.writeGenerated(), contains("import 'imported.dart' as i0;"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue