mirror of https://github.com/AMT-Cheif/drift.git
Make drift's tests pass with new analyzer
This commit is contained in:
parent
c2b319bc8e
commit
c5504237d5
|
@ -6,6 +6,178 @@ part of 'main.dart';
|
|||
// DriftElementId(asset:drift/example/main.dart, todo_items)
|
||||
// DriftElementId(asset:drift/example/main.dart, todo_categories)
|
||||
// DriftElementId(asset:drift/example/main.dart, customViewName)
|
||||
class TodoCategory extends DataClass implements Insertable<TodoCategory> {
|
||||
final int id;
|
||||
final String name;
|
||||
const TodoCategory({required this.id, required this.name});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
map['name'] = Variable<String>(name);
|
||||
return map;
|
||||
}
|
||||
|
||||
TodoCategoriesCompanion toCompanion(bool nullToAbsent) {
|
||||
return TodoCategoriesCompanion(
|
||||
id: Value(id),
|
||||
name: Value(name),
|
||||
);
|
||||
}
|
||||
|
||||
factory TodoCategory.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return TodoCategory(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
name: serializer.fromJson<String>(json['name']),
|
||||
);
|
||||
}
|
||||
factory TodoCategory.fromJsonString(String encodedJson,
|
||||
{ValueSerializer? serializer}) =>
|
||||
TodoCategory.fromJson(
|
||||
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
||||
serializer: serializer);
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'name': serializer.toJson<String>(name),
|
||||
};
|
||||
}
|
||||
|
||||
TodoCategory copyWith({int? id, String? name}) => TodoCategory(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('TodoCategory(')
|
||||
..write('id: $id, ')
|
||||
..write('name: $name')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, name);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is TodoCategory && other.id == this.id && other.name == this.name);
|
||||
}
|
||||
|
||||
class TodoCategoriesCompanion extends UpdateCompanion<TodoCategory> {
|
||||
final Value<int> id;
|
||||
final Value<String> name;
|
||||
const TodoCategoriesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.name = const Value.absent(),
|
||||
});
|
||||
TodoCategoriesCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
required String name,
|
||||
}) : name = Value(name);
|
||||
static Insertable<TodoCategory> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? name,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (name != null) 'name': name,
|
||||
});
|
||||
}
|
||||
|
||||
TodoCategoriesCompanion copyWith({Value<int>? id, Value<String>? name}) {
|
||||
return TodoCategoriesCompanion(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (name.present) {
|
||||
map['name'] = Variable<String>(name.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('TodoCategoriesCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('name: $name')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $TodoCategoriesTable extends TodoCategories
|
||||
with TableInfo<$TodoCategoriesTable, TodoCategory> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$TodoCategoriesTable(this.attachedDatabase, [this._alias]);
|
||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>(
|
||||
'id', aliasedName, false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'PRIMARY KEY AUTOINCREMENT');
|
||||
final VerificationMeta _nameMeta = const VerificationMeta('name');
|
||||
@override
|
||||
late final GeneratedColumn<String> name = GeneratedColumn<String>(
|
||||
'name', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, name];
|
||||
@override
|
||||
String get aliasedName => _alias ?? 'todo_categories';
|
||||
@override
|
||||
String get actualTableName => 'todo_categories';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<TodoCategory> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
}
|
||||
if (data.containsKey('name')) {
|
||||
context.handle(
|
||||
_nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_nameMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
TodoCategory map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return TodoCategory(
|
||||
id: attachedDatabase.options.types
|
||||
.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
name: attachedDatabase.options.types
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}name'])!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$TodoCategoriesTable createAlias(String alias) {
|
||||
return $TodoCategoriesTable(attachedDatabase, alias);
|
||||
}
|
||||
}
|
||||
|
||||
class TodoItem extends DataClass implements Insertable<TodoItem> {
|
||||
final int id;
|
||||
final String title;
|
||||
|
@ -290,178 +462,6 @@ class $TodoItemsTable extends TodoItems
|
|||
}
|
||||
}
|
||||
|
||||
class TodoCategory extends DataClass implements Insertable<TodoCategory> {
|
||||
final int id;
|
||||
final String name;
|
||||
const TodoCategory({required this.id, required this.name});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
map['name'] = Variable<String>(name);
|
||||
return map;
|
||||
}
|
||||
|
||||
TodoCategoriesCompanion toCompanion(bool nullToAbsent) {
|
||||
return TodoCategoriesCompanion(
|
||||
id: Value(id),
|
||||
name: Value(name),
|
||||
);
|
||||
}
|
||||
|
||||
factory TodoCategory.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return TodoCategory(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
name: serializer.fromJson<String>(json['name']),
|
||||
);
|
||||
}
|
||||
factory TodoCategory.fromJsonString(String encodedJson,
|
||||
{ValueSerializer? serializer}) =>
|
||||
TodoCategory.fromJson(
|
||||
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
||||
serializer: serializer);
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'name': serializer.toJson<String>(name),
|
||||
};
|
||||
}
|
||||
|
||||
TodoCategory copyWith({int? id, String? name}) => TodoCategory(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('TodoCategory(')
|
||||
..write('id: $id, ')
|
||||
..write('name: $name')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, name);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is TodoCategory && other.id == this.id && other.name == this.name);
|
||||
}
|
||||
|
||||
class TodoCategoriesCompanion extends UpdateCompanion<TodoCategory> {
|
||||
final Value<int> id;
|
||||
final Value<String> name;
|
||||
const TodoCategoriesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.name = const Value.absent(),
|
||||
});
|
||||
TodoCategoriesCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
required String name,
|
||||
}) : name = Value(name);
|
||||
static Insertable<TodoCategory> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? name,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (name != null) 'name': name,
|
||||
});
|
||||
}
|
||||
|
||||
TodoCategoriesCompanion copyWith({Value<int>? id, Value<String>? name}) {
|
||||
return TodoCategoriesCompanion(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (name.present) {
|
||||
map['name'] = Variable<String>(name.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('TodoCategoriesCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('name: $name')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $TodoCategoriesTable extends TodoCategories
|
||||
with TableInfo<$TodoCategoriesTable, TodoCategory> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$TodoCategoriesTable(this.attachedDatabase, [this._alias]);
|
||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>(
|
||||
'id', aliasedName, false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'PRIMARY KEY AUTOINCREMENT');
|
||||
final VerificationMeta _nameMeta = const VerificationMeta('name');
|
||||
@override
|
||||
late final GeneratedColumn<String> name = GeneratedColumn<String>(
|
||||
'name', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, name];
|
||||
@override
|
||||
String get aliasedName => _alias ?? 'todo_categories';
|
||||
@override
|
||||
String get actualTableName => 'todo_categories';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<TodoCategory> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
}
|
||||
if (data.containsKey('name')) {
|
||||
context.handle(
|
||||
_nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_nameMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
TodoCategory map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return TodoCategory(
|
||||
id: attachedDatabase.options.types
|
||||
.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
name: attachedDatabase.options.types
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}name'])!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$TodoCategoriesTable createAlias(String alias) {
|
||||
return $TodoCategoriesTable(attachedDatabase, alias);
|
||||
}
|
||||
}
|
||||
|
||||
class TodoCategoryItemCountData extends DataClass {
|
||||
final String name;
|
||||
final int? itemCount;
|
||||
|
@ -680,8 +680,8 @@ class $TodoItemWithCategoryNameViewView extends ViewInfo<
|
|||
abstract class _$Database extends GeneratedDatabase {
|
||||
_$Database(QueryExecutor e) : super(e);
|
||||
_$Database.connect(DatabaseConnection c) : super.connect(c);
|
||||
late final $TodoItemsTable todoItems = $TodoItemsTable(this);
|
||||
late final $TodoCategoriesTable todoCategories = $TodoCategoriesTable(this);
|
||||
late final $TodoItemsTable todoItems = $TodoItemsTable(this);
|
||||
late final $TodoCategoryItemCountView todoCategoryItemCount =
|
||||
$TodoCategoryItemCountView(this);
|
||||
late final $TodoItemWithCategoryNameViewView customViewName =
|
||||
|
@ -691,5 +691,5 @@ abstract class _$Database extends GeneratedDatabase {
|
|||
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
||||
@override
|
||||
List<DatabaseSchemaEntity> get allSchemaEntities =>
|
||||
[todoItems, todoCategories, todoCategoryItemCount, customViewName];
|
||||
[todoCategories, todoItems, todoCategoryItemCount, customViewName];
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ void main() {
|
|||
'CREATE TABLE IF NOT EXISTS "todos" '
|
||||
'("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "title" TEXT NULL, '
|
||||
'"content" TEXT NOT NULL, "target_date" INTEGER NULL UNIQUE, '
|
||||
'"category" INTEGER NULL REFERENCES "categories" ("id"), '
|
||||
'"category" INTEGER NULL REFERENCES categories (id), '
|
||||
'UNIQUE ("title", "category"), UNIQUE ("title", "target_date"));',
|
||||
[]));
|
||||
|
||||
|
@ -41,7 +41,7 @@ void main() {
|
|||
'CREATE TABLE IF NOT EXISTS "users" ('
|
||||
'"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '
|
||||
'"name" TEXT NOT NULL UNIQUE, '
|
||||
'"is_awesome" INTEGER NOT NULL DEFAULT 1 CHECK ("is_awesome" IN (0, 1)), '
|
||||
'"is_awesome" INTEGER NOT NULL DEFAULT 1 CHECK (is_awesome IN (0, 1)), '
|
||||
'"profile_picture" BLOB NOT NULL, '
|
||||
'"creation_time" INTEGER NOT NULL '
|
||||
"DEFAULT (CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)) "
|
||||
|
@ -98,7 +98,7 @@ void main() {
|
|||
'CREATE TABLE IF NOT EXISTS "users" '
|
||||
'("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '
|
||||
'"name" TEXT NOT NULL UNIQUE, '
|
||||
'"is_awesome" INTEGER NOT NULL DEFAULT 1 CHECK ("is_awesome" IN (0, 1)), '
|
||||
'"is_awesome" INTEGER NOT NULL DEFAULT 1 CHECK (is_awesome IN (0, 1)), '
|
||||
'"profile_picture" BLOB NOT NULL, '
|
||||
'"creation_time" INTEGER NOT NULL '
|
||||
"DEFAULT (CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)) "
|
||||
|
@ -145,7 +145,7 @@ void main() {
|
|||
|
||||
verify(mockExecutor.runCustom('ALTER TABLE "users" ADD COLUMN '
|
||||
'"is_awesome" INTEGER NOT NULL DEFAULT 1 '
|
||||
'CHECK ("is_awesome" IN (0, 1));'));
|
||||
'CHECK (is_awesome IN (0, 1));'));
|
||||
});
|
||||
|
||||
test('renames columns', () async {
|
||||
|
|
|
@ -52,7 +52,7 @@ class $NoIdsTable extends Table with TableInfo<$NoIdsTable, NoIdRow> {
|
|||
'payload', aliasedName, false,
|
||||
type: DriftSqlType.blob,
|
||||
requiredDuringInsert: true,
|
||||
defaultConstraints: 'PRIMARY KEY');
|
||||
$customConstraints: 'NOT NULL PRIMARY KEY');
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [payload];
|
||||
@override
|
||||
|
@ -92,6 +92,8 @@ class $NoIdsTable extends Table with TableInfo<$NoIdsTable, NoIdRow> {
|
|||
@override
|
||||
bool get withoutRowId => true;
|
||||
@override
|
||||
List<String> get customConstraints => const [];
|
||||
@override
|
||||
bool get dontWriteConstraints => true;
|
||||
}
|
||||
|
||||
|
@ -225,13 +227,14 @@ class $WithDefaultsTable extends Table
|
|||
'a', aliasedName, true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: 'DEFAULT \'something\'',
|
||||
defaultValue: const CustomExpression('\'something\''));
|
||||
final VerificationMeta _bMeta = const VerificationMeta('b');
|
||||
late final GeneratedColumn<int> b = GeneratedColumn<int>(
|
||||
'b', aliasedName, true,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'UNIQUE');
|
||||
$customConstraints: 'UNIQUE');
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [a, b];
|
||||
@override
|
||||
|
@ -270,6 +273,8 @@ class $WithDefaultsTable extends Table
|
|||
return $WithDefaultsTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> get customConstraints => const [];
|
||||
@override
|
||||
bool get dontWriteConstraints => true;
|
||||
}
|
||||
|
@ -424,15 +429,21 @@ class $WithConstraintsTable extends Table
|
|||
final VerificationMeta _aMeta = const VerificationMeta('a');
|
||||
late final GeneratedColumn<String> a = GeneratedColumn<String>(
|
||||
'a', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false);
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: '');
|
||||
final VerificationMeta _bMeta = const VerificationMeta('b');
|
||||
late final GeneratedColumn<int> b = GeneratedColumn<int>(
|
||||
'b', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: 'NOT NULL');
|
||||
final VerificationMeta _cMeta = const VerificationMeta('c');
|
||||
late final GeneratedColumn<double> c = GeneratedColumn<double>(
|
||||
'c', aliasedName, true,
|
||||
type: DriftSqlType.double, requiredDuringInsert: false);
|
||||
type: DriftSqlType.double,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: '');
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [a, b, c];
|
||||
@override
|
||||
|
@ -478,6 +489,9 @@ class $WithConstraintsTable extends Table
|
|||
return $WithConstraintsTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> get customConstraints =>
|
||||
const ['FOREIGN KEY(a, b)REFERENCES with_defaults(a, b)'];
|
||||
@override
|
||||
bool get dontWriteConstraints => true;
|
||||
}
|
||||
|
@ -676,23 +690,29 @@ class $ConfigTable extends Table with TableInfo<$ConfigTable, Config> {
|
|||
'config_key', aliasedName, false,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
defaultConstraints: 'PRIMARY KEY');
|
||||
$customConstraints: 'NOT NULL PRIMARY KEY');
|
||||
final VerificationMeta _configValueMeta =
|
||||
const VerificationMeta('configValue');
|
||||
late final GeneratedColumn<String> configValue = GeneratedColumn<String>(
|
||||
'config_value', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false);
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: '');
|
||||
final VerificationMeta _syncStateMeta = const VerificationMeta('syncState');
|
||||
late final GeneratedColumnWithTypeConverter<SyncType?, int> syncState =
|
||||
GeneratedColumn<int>('sync_state', aliasedName, true,
|
||||
type: DriftSqlType.int, requiredDuringInsert: false)
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: '')
|
||||
.withConverter<SyncType?>($ConfigTable.$convertersyncStaten);
|
||||
final VerificationMeta _syncStateImplicitMeta =
|
||||
const VerificationMeta('syncStateImplicit');
|
||||
late final GeneratedColumnWithTypeConverter<SyncType?, int>
|
||||
syncStateImplicit = GeneratedColumn<int>(
|
||||
'sync_state_implicit', aliasedName, true,
|
||||
type: DriftSqlType.int, requiredDuringInsert: false)
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: '')
|
||||
.withConverter<SyncType?>($ConfigTable.$convertersyncStateImplicitn);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns =>
|
||||
|
@ -758,6 +778,8 @@ class $ConfigTable extends Table with TableInfo<$ConfigTable, Config> {
|
|||
@override
|
||||
bool get isStrict => true;
|
||||
@override
|
||||
List<String> get customConstraints => const [];
|
||||
@override
|
||||
bool get dontWriteConstraints => true;
|
||||
}
|
||||
|
||||
|
@ -941,22 +963,28 @@ class $MytableTable extends Table with TableInfo<$MytableTable, MytableData> {
|
|||
final VerificationMeta _someidMeta = const VerificationMeta('someid');
|
||||
late final GeneratedColumn<int> someid = GeneratedColumn<int>(
|
||||
'someid', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: false);
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: 'NOT NULL');
|
||||
final VerificationMeta _sometextMeta = const VerificationMeta('sometext');
|
||||
late final GeneratedColumn<String> sometext = GeneratedColumn<String>(
|
||||
'sometext', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false);
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: '');
|
||||
final VerificationMeta _isInsertingMeta =
|
||||
const VerificationMeta('isInserting');
|
||||
late final GeneratedColumn<bool> isInserting = GeneratedColumn<bool>(
|
||||
'is_inserting', aliasedName, true,
|
||||
type: DriftSqlType.bool,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'CHECK (is_inserting IN (0, 1))');
|
||||
$customConstraints: '');
|
||||
final VerificationMeta _somedateMeta = const VerificationMeta('somedate');
|
||||
late final GeneratedColumn<DateTime> somedate = GeneratedColumn<DateTime>(
|
||||
'somedate', aliasedName, true,
|
||||
type: DriftSqlType.dateTime, requiredDuringInsert: false);
|
||||
type: DriftSqlType.dateTime,
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints: '');
|
||||
@override
|
||||
List<GeneratedColumn> get $columns =>
|
||||
[someid, sometext, isInserting, somedate];
|
||||
|
@ -1013,6 +1041,8 @@ class $MytableTable extends Table with TableInfo<$MytableTable, MytableData> {
|
|||
return $MytableTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> get customConstraints => const ['PRIMARY KEY(someid DESC)'];
|
||||
@override
|
||||
bool get dontWriteConstraints => true;
|
||||
}
|
||||
|
@ -1160,15 +1190,21 @@ class $EmailTable extends Table
|
|||
final VerificationMeta _senderMeta = const VerificationMeta('sender');
|
||||
late final GeneratedColumn<String> sender = GeneratedColumn<String>(
|
||||
'sender', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: '');
|
||||
final VerificationMeta _titleMeta = const VerificationMeta('title');
|
||||
late final GeneratedColumn<String> title = GeneratedColumn<String>(
|
||||
'title', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: '');
|
||||
final VerificationMeta _bodyMeta = const VerificationMeta('body');
|
||||
late final GeneratedColumn<String> body = GeneratedColumn<String>(
|
||||
'body', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: '');
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [sender, title, body];
|
||||
@override
|
||||
|
@ -1221,6 +1257,8 @@ class $EmailTable extends Table
|
|||
return $EmailTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> get customConstraints => const [];
|
||||
@override
|
||||
bool get dontWriteConstraints => true;
|
||||
@override
|
||||
|
@ -1352,11 +1390,15 @@ class $WeirdTableTable extends Table
|
|||
final VerificationMeta _sqlClassMeta = const VerificationMeta('sqlClass');
|
||||
late final GeneratedColumn<int> sqlClass = GeneratedColumn<int>(
|
||||
'class', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: 'NOT NULL');
|
||||
final VerificationMeta _textColumnMeta = const VerificationMeta('textColumn');
|
||||
late final GeneratedColumn<String> textColumn = GeneratedColumn<String>(
|
||||
'text', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: 'NOT NULL');
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [sqlClass, textColumn];
|
||||
@override
|
||||
|
@ -1401,6 +1443,8 @@ class $WeirdTableTable extends Table
|
|||
return $WeirdTableTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> get customConstraints => const [];
|
||||
@override
|
||||
bool get dontWriteConstraints => true;
|
||||
}
|
||||
|
@ -1815,6 +1859,18 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
|
|||
'INSERT INTO config (config_key, config_value) VALUES (\'key\', \'values\')')
|
||||
];
|
||||
@override
|
||||
StreamQueryUpdateRules get streamUpdateRules => const StreamQueryUpdateRules(
|
||||
[
|
||||
WritePropagation(
|
||||
on: TableUpdateQuery.onTableName('config',
|
||||
limitUpdateKind: UpdateKind.insert),
|
||||
result: [
|
||||
TableUpdate('with_defaults', kind: UpdateKind.insert),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
@override
|
||||
DriftDatabaseOptions get options =>
|
||||
const DriftDatabaseOptions(storeDateTimeAsText: true);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,260 @@ part of 'todos.dart';
|
|||
// DriftElementId(asset:drift/test/generated/todos.dart, todos)
|
||||
// DriftElementId(asset:drift/test/generated/todos.dart, categories)
|
||||
// DriftElementId(asset:drift/test/generated/todos.dart, todo_with_category_view)
|
||||
class Category extends DataClass implements Insertable<Category> {
|
||||
final int id;
|
||||
final String description;
|
||||
final CategoryPriority priority;
|
||||
final String descriptionInUpperCase;
|
||||
const Category(
|
||||
{required this.id,
|
||||
required this.description,
|
||||
required this.priority,
|
||||
required this.descriptionInUpperCase});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
map['desc'] = Variable<String>(description);
|
||||
{
|
||||
final converter = $CategoriesTable.$converterpriority;
|
||||
map['priority'] = Variable<int>(converter.toSql(priority));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
CategoriesCompanion toCompanion(bool nullToAbsent) {
|
||||
return CategoriesCompanion(
|
||||
id: Value(id),
|
||||
description: Value(description),
|
||||
priority: Value(priority),
|
||||
);
|
||||
}
|
||||
|
||||
factory Category.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return Category(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
description: serializer.fromJson<String>(json['description']),
|
||||
priority: serializer.fromJson<CategoryPriority>(json['priority']),
|
||||
descriptionInUpperCase:
|
||||
serializer.fromJson<String>(json['descriptionInUpperCase']),
|
||||
);
|
||||
}
|
||||
factory Category.fromJsonString(String encodedJson,
|
||||
{ValueSerializer? serializer}) =>
|
||||
Category.fromJson(
|
||||
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
||||
serializer: serializer);
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'description': serializer.toJson<String>(description),
|
||||
'priority': serializer.toJson<CategoryPriority>(priority),
|
||||
'descriptionInUpperCase':
|
||||
serializer.toJson<String>(descriptionInUpperCase),
|
||||
};
|
||||
}
|
||||
|
||||
Category copyWith(
|
||||
{int? id,
|
||||
String? description,
|
||||
CategoryPriority? priority,
|
||||
String? descriptionInUpperCase}) =>
|
||||
Category(
|
||||
id: id ?? this.id,
|
||||
description: description ?? this.description,
|
||||
priority: priority ?? this.priority,
|
||||
descriptionInUpperCase:
|
||||
descriptionInUpperCase ?? this.descriptionInUpperCase,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('Category(')
|
||||
..write('id: $id, ')
|
||||
..write('description: $description, ')
|
||||
..write('priority: $priority, ')
|
||||
..write('descriptionInUpperCase: $descriptionInUpperCase')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(id, description, priority, descriptionInUpperCase);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is Category &&
|
||||
other.id == this.id &&
|
||||
other.description == this.description &&
|
||||
other.priority == this.priority &&
|
||||
other.descriptionInUpperCase == this.descriptionInUpperCase);
|
||||
}
|
||||
|
||||
class CategoriesCompanion extends UpdateCompanion<Category> {
|
||||
final Value<int> id;
|
||||
final Value<String> description;
|
||||
final Value<CategoryPriority> priority;
|
||||
const CategoriesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.description = const Value.absent(),
|
||||
this.priority = const Value.absent(),
|
||||
});
|
||||
CategoriesCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
required String description,
|
||||
this.priority = const Value.absent(),
|
||||
}) : description = Value(description);
|
||||
static Insertable<Category> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? description,
|
||||
Expression<int>? priority,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (description != null) 'desc': description,
|
||||
if (priority != null) 'priority': priority,
|
||||
});
|
||||
}
|
||||
|
||||
CategoriesCompanion copyWith(
|
||||
{Value<int>? id,
|
||||
Value<String>? description,
|
||||
Value<CategoryPriority>? priority}) {
|
||||
return CategoriesCompanion(
|
||||
id: id ?? this.id,
|
||||
description: description ?? this.description,
|
||||
priority: priority ?? this.priority,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (description.present) {
|
||||
map['desc'] = Variable<String>(description.value);
|
||||
}
|
||||
if (priority.present) {
|
||||
final converter = $CategoriesTable.$converterpriority;
|
||||
map['priority'] = Variable<int>(converter.toSql(priority.value));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('CategoriesCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('description: $description, ')
|
||||
..write('priority: $priority')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $CategoriesTable extends Categories
|
||||
with TableInfo<$CategoriesTable, Category> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$CategoriesTable(this.attachedDatabase, [this._alias]);
|
||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>(
|
||||
'id', aliasedName, false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'PRIMARY KEY AUTOINCREMENT');
|
||||
final VerificationMeta _descriptionMeta =
|
||||
const VerificationMeta('description');
|
||||
@override
|
||||
late final GeneratedColumn<String> description = GeneratedColumn<String>(
|
||||
'desc', aliasedName, false,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: 'NOT NULL UNIQUE');
|
||||
final VerificationMeta _priorityMeta = const VerificationMeta('priority');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<CategoryPriority, int> priority =
|
||||
GeneratedColumn<int>('priority', aliasedName, false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant(0))
|
||||
.withConverter<CategoryPriority>($CategoriesTable.$converterpriority);
|
||||
final VerificationMeta _descriptionInUpperCaseMeta =
|
||||
const VerificationMeta('descriptionInUpperCase');
|
||||
@override
|
||||
late final GeneratedColumn<String> descriptionInUpperCase =
|
||||
GeneratedColumn<String>('description_in_upper_case', aliasedName, false,
|
||||
generatedAs: GeneratedAs(description.upper(), false),
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns =>
|
||||
[id, description, priority, descriptionInUpperCase];
|
||||
@override
|
||||
String get aliasedName => _alias ?? 'categories';
|
||||
@override
|
||||
String get actualTableName => 'categories';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<Category> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
}
|
||||
if (data.containsKey('desc')) {
|
||||
context.handle(_descriptionMeta,
|
||||
description.isAcceptableOrUnknown(data['desc']!, _descriptionMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_descriptionMeta);
|
||||
}
|
||||
context.handle(_priorityMeta, const VerificationResult.success());
|
||||
if (data.containsKey('description_in_upper_case')) {
|
||||
context.handle(
|
||||
_descriptionInUpperCaseMeta,
|
||||
descriptionInUpperCase.isAcceptableOrUnknown(
|
||||
data['description_in_upper_case']!, _descriptionInUpperCaseMeta));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
Category map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return Category(
|
||||
id: attachedDatabase.options.types
|
||||
.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
description: attachedDatabase.options.types
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}desc'])!,
|
||||
priority: $CategoriesTable.$converterpriority.fromSql(attachedDatabase
|
||||
.options.types
|
||||
.read(DriftSqlType.int, data['${effectivePrefix}priority'])!),
|
||||
descriptionInUpperCase: attachedDatabase.options.types.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}description_in_upper_case'])!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$CategoriesTable createAlias(String alias) {
|
||||
return $CategoriesTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static TypeConverter<CategoryPriority, int> $converterpriority =
|
||||
const EnumIndexConverter<CategoryPriority>(CategoryPriority.values);
|
||||
}
|
||||
|
||||
class TodoEntry extends DataClass implements Insertable<TodoEntry> {
|
||||
final int id;
|
||||
final String? title;
|
||||
|
@ -309,260 +563,6 @@ class $TodosTableTable extends TodosTable
|
|||
}
|
||||
}
|
||||
|
||||
class Category extends DataClass implements Insertable<Category> {
|
||||
final int id;
|
||||
final String description;
|
||||
final CategoryPriority priority;
|
||||
final String descriptionInUpperCase;
|
||||
const Category(
|
||||
{required this.id,
|
||||
required this.description,
|
||||
required this.priority,
|
||||
required this.descriptionInUpperCase});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
map['desc'] = Variable<String>(description);
|
||||
{
|
||||
final converter = $CategoriesTable.$converterpriority;
|
||||
map['priority'] = Variable<int>(converter.toSql(priority));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
CategoriesCompanion toCompanion(bool nullToAbsent) {
|
||||
return CategoriesCompanion(
|
||||
id: Value(id),
|
||||
description: Value(description),
|
||||
priority: Value(priority),
|
||||
);
|
||||
}
|
||||
|
||||
factory Category.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return Category(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
description: serializer.fromJson<String>(json['description']),
|
||||
priority: serializer.fromJson<CategoryPriority>(json['priority']),
|
||||
descriptionInUpperCase:
|
||||
serializer.fromJson<String>(json['descriptionInUpperCase']),
|
||||
);
|
||||
}
|
||||
factory Category.fromJsonString(String encodedJson,
|
||||
{ValueSerializer? serializer}) =>
|
||||
Category.fromJson(
|
||||
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
||||
serializer: serializer);
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'description': serializer.toJson<String>(description),
|
||||
'priority': serializer.toJson<CategoryPriority>(priority),
|
||||
'descriptionInUpperCase':
|
||||
serializer.toJson<String>(descriptionInUpperCase),
|
||||
};
|
||||
}
|
||||
|
||||
Category copyWith(
|
||||
{int? id,
|
||||
String? description,
|
||||
CategoryPriority? priority,
|
||||
String? descriptionInUpperCase}) =>
|
||||
Category(
|
||||
id: id ?? this.id,
|
||||
description: description ?? this.description,
|
||||
priority: priority ?? this.priority,
|
||||
descriptionInUpperCase:
|
||||
descriptionInUpperCase ?? this.descriptionInUpperCase,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('Category(')
|
||||
..write('id: $id, ')
|
||||
..write('description: $description, ')
|
||||
..write('priority: $priority, ')
|
||||
..write('descriptionInUpperCase: $descriptionInUpperCase')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(id, description, priority, descriptionInUpperCase);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is Category &&
|
||||
other.id == this.id &&
|
||||
other.description == this.description &&
|
||||
other.priority == this.priority &&
|
||||
other.descriptionInUpperCase == this.descriptionInUpperCase);
|
||||
}
|
||||
|
||||
class CategoriesCompanion extends UpdateCompanion<Category> {
|
||||
final Value<int> id;
|
||||
final Value<String> description;
|
||||
final Value<CategoryPriority> priority;
|
||||
const CategoriesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.description = const Value.absent(),
|
||||
this.priority = const Value.absent(),
|
||||
});
|
||||
CategoriesCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
required String description,
|
||||
this.priority = const Value.absent(),
|
||||
}) : description = Value(description);
|
||||
static Insertable<Category> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? description,
|
||||
Expression<int>? priority,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (description != null) 'desc': description,
|
||||
if (priority != null) 'priority': priority,
|
||||
});
|
||||
}
|
||||
|
||||
CategoriesCompanion copyWith(
|
||||
{Value<int>? id,
|
||||
Value<String>? description,
|
||||
Value<CategoryPriority>? priority}) {
|
||||
return CategoriesCompanion(
|
||||
id: id ?? this.id,
|
||||
description: description ?? this.description,
|
||||
priority: priority ?? this.priority,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (description.present) {
|
||||
map['desc'] = Variable<String>(description.value);
|
||||
}
|
||||
if (priority.present) {
|
||||
final converter = $CategoriesTable.$converterpriority;
|
||||
map['priority'] = Variable<int>(converter.toSql(priority.value));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('CategoriesCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('description: $description, ')
|
||||
..write('priority: $priority')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $CategoriesTable extends Categories
|
||||
with TableInfo<$CategoriesTable, Category> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$CategoriesTable(this.attachedDatabase, [this._alias]);
|
||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>(
|
||||
'id', aliasedName, false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'PRIMARY KEY AUTOINCREMENT');
|
||||
final VerificationMeta _descriptionMeta =
|
||||
const VerificationMeta('description');
|
||||
@override
|
||||
late final GeneratedColumn<String> description = GeneratedColumn<String>(
|
||||
'desc', aliasedName, false,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: 'NOT NULL UNIQUE');
|
||||
final VerificationMeta _priorityMeta = const VerificationMeta('priority');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<CategoryPriority, int> priority =
|
||||
GeneratedColumn<int>('priority', aliasedName, false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant(0))
|
||||
.withConverter<CategoryPriority>($CategoriesTable.$converterpriority);
|
||||
final VerificationMeta _descriptionInUpperCaseMeta =
|
||||
const VerificationMeta('descriptionInUpperCase');
|
||||
@override
|
||||
late final GeneratedColumn<String> descriptionInUpperCase =
|
||||
GeneratedColumn<String>('description_in_upper_case', aliasedName, false,
|
||||
generatedAs: GeneratedAs(description.upper(), false),
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns =>
|
||||
[id, description, priority, descriptionInUpperCase];
|
||||
@override
|
||||
String get aliasedName => _alias ?? 'categories';
|
||||
@override
|
||||
String get actualTableName => 'categories';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<Category> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
}
|
||||
if (data.containsKey('desc')) {
|
||||
context.handle(_descriptionMeta,
|
||||
description.isAcceptableOrUnknown(data['desc']!, _descriptionMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_descriptionMeta);
|
||||
}
|
||||
context.handle(_priorityMeta, const VerificationResult.success());
|
||||
if (data.containsKey('description_in_upper_case')) {
|
||||
context.handle(
|
||||
_descriptionInUpperCaseMeta,
|
||||
descriptionInUpperCase.isAcceptableOrUnknown(
|
||||
data['description_in_upper_case']!, _descriptionInUpperCaseMeta));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
Category map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return Category(
|
||||
id: attachedDatabase.options.types
|
||||
.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
description: attachedDatabase.options.types
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}desc'])!,
|
||||
priority: $CategoriesTable.$converterpriority.fromSql(attachedDatabase
|
||||
.options.types
|
||||
.read(DriftSqlType.int, data['${effectivePrefix}priority'])!),
|
||||
descriptionInUpperCase: attachedDatabase.options.types.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}description_in_upper_case'])!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$CategoriesTable createAlias(String alias) {
|
||||
return $CategoriesTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static TypeConverter<CategoryPriority, int> $converterpriority =
|
||||
const EnumIndexConverter<CategoryPriority>(CategoryPriority.values);
|
||||
}
|
||||
|
||||
class User extends DataClass implements Insertable<User> {
|
||||
final int id;
|
||||
final String name;
|
||||
|
@ -1590,8 +1590,8 @@ class $TodoWithCategoryViewView
|
|||
abstract class _$TodoDb extends GeneratedDatabase {
|
||||
_$TodoDb(QueryExecutor e) : super(e);
|
||||
_$TodoDb.connect(DatabaseConnection c) : super.connect(c);
|
||||
late final $TodosTableTable todosTable = $TodosTableTable(this);
|
||||
late final $CategoriesTable categories = $CategoriesTable(this);
|
||||
late final $TodosTableTable todosTable = $TodosTableTable(this);
|
||||
late final $UsersTable users = $UsersTable(this);
|
||||
late final $SharedTodosTable sharedTodos = $SharedTodosTable(this);
|
||||
late final $TableWithoutPKTable tableWithoutPK = $TableWithoutPKTable(this);
|
||||
|
@ -1673,8 +1673,8 @@ abstract class _$TodoDb extends GeneratedDatabase {
|
|||
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
||||
@override
|
||||
List<DatabaseSchemaEntity> get allSchemaEntities => [
|
||||
todosTable,
|
||||
categories,
|
||||
todosTable,
|
||||
users,
|
||||
sharedTodos,
|
||||
tableWithoutPK,
|
||||
|
@ -1738,10 +1738,10 @@ class AllTodosWithCategoryResult extends CustomResultSet {
|
|||
mixin _$SomeDaoMixin on DatabaseAccessor<TodoDb> {
|
||||
$UsersTable get users => attachedDatabase.users;
|
||||
$SharedTodosTable get sharedTodos => attachedDatabase.sharedTodos;
|
||||
$CategoriesTable get categories => attachedDatabase.categories;
|
||||
$TodosTableTable get todosTable => attachedDatabase.todosTable;
|
||||
$TodoWithCategoryViewView get todoWithCategoryView =>
|
||||
attachedDatabase.todoWithCategoryView;
|
||||
$CategoriesTable get categories => attachedDatabase.categories;
|
||||
Selectable<TodoEntry> todosForUser({required int user}) {
|
||||
return customSelect(
|
||||
'SELECT t.* FROM todos AS t INNER JOIN shared_todos AS st ON st.todo = t.id INNER JOIN users AS u ON u.id = st.user WHERE u.id = ?1',
|
||||
|
|
|
@ -15,11 +15,11 @@ const _createWithDefaults = 'CREATE TABLE IF NOT EXISTS "with_defaults" ('
|
|||
|
||||
const _createWithConstraints = 'CREATE TABLE IF NOT EXISTS "with_constraints" ('
|
||||
'"a" TEXT, "b" INTEGER NOT NULL, "c" REAL, '
|
||||
'FOREIGN KEY (a, b) REFERENCES with_defaults (a, b)'
|
||||
'FOREIGN KEY(a, b)REFERENCES with_defaults(a, b)'
|
||||
');';
|
||||
|
||||
const _createConfig = 'CREATE TABLE IF NOT EXISTS "config" ('
|
||||
'"config_key" TEXT not null primary key, '
|
||||
'"config_key" TEXT NOT NULL PRIMARY KEY, '
|
||||
'"config_value" TEXT, '
|
||||
'"sync_state" INTEGER, '
|
||||
'"sync_state_implicit" INTEGER) STRICT;';
|
||||
|
@ -29,7 +29,7 @@ const _createMyTable = 'CREATE TABLE IF NOT EXISTS "mytable" ('
|
|||
'"sometext" TEXT, '
|
||||
'"is_inserting" INTEGER, '
|
||||
'"somedate" TEXT, '
|
||||
'PRIMARY KEY (someid DESC)'
|
||||
'PRIMARY KEY(someid DESC)'
|
||||
');';
|
||||
|
||||
const _createEmail = 'CREATE VIRTUAL TABLE IF NOT EXISTS "email" USING '
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
import 'results/results.dart';
|
||||
|
||||
/// Transforms queries given in [inputs] so that their result sets respect
|
||||
/// custom result class names specified by the user.
|
||||
///
|
||||
/// The "custom result class name" feature can be used to change the name of a
|
||||
/// result class and to generate the same result class for multiple custom
|
||||
/// queries.
|
||||
///
|
||||
/// Merging result classes of queries will always happen from the point of a
|
||||
/// database class or dao. This means that incompatible queries can have the
|
||||
/// same result class name as long as they're not imported into the same moor
|
||||
/// accessor.
|
||||
///
|
||||
/// This feature doesn't work when we apply other simplifications to query, so
|
||||
/// we report an error if the query returns a single column or if it has a
|
||||
/// matching table. This restriction might be lifted in the future, but it makes
|
||||
/// the implementation easier.
|
||||
Map<SqlSelectQuery, SqlSelectQuery> transformCustomResultClasses(
|
||||
Iterable<SqlQuery> inputs,
|
||||
void Function(String) reportError,
|
||||
) {
|
||||
// A group of queries sharing a common result class name.
|
||||
final queryGroups = <String, List<SqlSelectQuery>>{};
|
||||
|
||||
// Find and group queries with the same result class name
|
||||
for (final query in inputs) {
|
||||
if (query is! SqlSelectQuery) continue;
|
||||
final selectQuery = query;
|
||||
|
||||
// Doesn't use a custom result class, so it's not affected by this
|
||||
if (selectQuery.requestedResultClass == null) continue;
|
||||
|
||||
// Alright, the query wants a custom result class, but is it allowed to
|
||||
// have one?
|
||||
if (selectQuery.resultSet.singleColumn) {
|
||||
reportError("The query ${selectQuery.name} can't have a custom name as "
|
||||
'it only returns one column.');
|
||||
continue;
|
||||
}
|
||||
if (selectQuery.resultSet.matchingTable != null) {
|
||||
reportError("The query ${selectQuery.name} can't have a custom name as "
|
||||
'it returns a single table data class.');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (selectQuery.requestedResultClass != null) {
|
||||
queryGroups
|
||||
.putIfAbsent(selectQuery.requestedResultClass!, () => [])
|
||||
.add(selectQuery);
|
||||
}
|
||||
}
|
||||
|
||||
final replacements = <SqlSelectQuery, SqlSelectQuery>{};
|
||||
|
||||
for (final group in queryGroups.entries) {
|
||||
final resultSetName = group.key;
|
||||
final queries = group.value;
|
||||
|
||||
if (!_resultSetsCompatible(queries.map((e) => e.resultSet))) {
|
||||
reportError(
|
||||
'Could not merge result sets to $resultSetName: The queries '
|
||||
'have different columns and types.',
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
final referenceResult = queries.first.resultSet;
|
||||
final dartNames = {
|
||||
for (final column in referenceResult.columns)
|
||||
column: referenceResult.dartNameFor(column),
|
||||
};
|
||||
|
||||
var isFirst = true;
|
||||
for (final query in queries) {
|
||||
final newResultSet = InferredResultSet(
|
||||
null,
|
||||
query.resultSet.columns,
|
||||
resultClassName: resultSetName,
|
||||
nestedResults: query.resultSet.nestedResults,
|
||||
// Only generate a result class for the first query in the group
|
||||
dontGenerateResultClass: !isFirst,
|
||||
);
|
||||
|
||||
// Make sure compatible columns in the two result sets have the same
|
||||
// Dart name.
|
||||
newResultSet.forceDartNames({
|
||||
for (final entry in dartNames.entries)
|
||||
newResultSet.columns.singleWhere((e) => e.compatibleTo(entry.key)):
|
||||
entry.value,
|
||||
});
|
||||
|
||||
final newQuery = query.replaceResultSet(newResultSet);
|
||||
replacements[query] = newQuery;
|
||||
isFirst = false;
|
||||
}
|
||||
}
|
||||
|
||||
return replacements;
|
||||
}
|
||||
|
||||
bool _resultSetsCompatible(Iterable<InferredResultSet> resultSets) {
|
||||
InferredResultSet? last;
|
||||
|
||||
for (final current in resultSets) {
|
||||
if (last != null && !last.isCompatibleTo(current)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
last = current;
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -84,10 +84,16 @@ class DriftTableResolver extends LocalElementResolver<DiscoveredDriftTable> {
|
|||
// can't read the constraints.
|
||||
final sqlConstraints =
|
||||
column.hasDefinition ? column.constraints : const <Never>[];
|
||||
final customConstraintsForDrift = StringBuffer();
|
||||
|
||||
for (final constraint in sqlConstraints) {
|
||||
var writeIntoTable = true;
|
||||
|
||||
if (constraint is DriftDartName) {
|
||||
overriddenDartName = constraint.dartName;
|
||||
writeIntoTable = false;
|
||||
} else if (constraint is MappedBy) {
|
||||
writeIntoTable = false;
|
||||
if (converter != null) {
|
||||
reportError(DriftAnalysisError.inDriftFile(
|
||||
constraint,
|
||||
|
@ -150,6 +156,13 @@ class DriftTableResolver extends LocalElementResolver<DiscoveredDriftTable> {
|
|||
} else if (constraint is sql.UniqueColumn) {
|
||||
constraints.add(UniqueColumn());
|
||||
}
|
||||
|
||||
if (writeIntoTable) {
|
||||
if (customConstraintsForDrift.isNotEmpty) {
|
||||
customConstraintsForDrift.write(' ');
|
||||
}
|
||||
customConstraintsForDrift.write(constraint.toSql());
|
||||
}
|
||||
}
|
||||
|
||||
columns.add(DriftColumn(
|
||||
|
@ -160,6 +173,7 @@ class DriftTableResolver extends LocalElementResolver<DiscoveredDriftTable> {
|
|||
constraints: constraints,
|
||||
typeConverter: converter,
|
||||
defaultArgument: defaultArgument,
|
||||
customConstraints: customConstraintsForDrift.toString(),
|
||||
declaration: DriftDeclaration.driftFile(
|
||||
column.definition?.nameToken ?? stmt,
|
||||
state.ownId.libraryUri,
|
||||
|
@ -168,9 +182,12 @@ class DriftTableResolver extends LocalElementResolver<DiscoveredDriftTable> {
|
|||
}
|
||||
|
||||
VirtualTableData? virtualTableData;
|
||||
final sqlTableConstraints = <String>[];
|
||||
|
||||
if (stmt is CreateTableStatement) {
|
||||
for (final constraint in stmt.tableConstraints) {
|
||||
sqlTableConstraints.add(constraint.toSql());
|
||||
|
||||
if (constraint is ForeignKeyTableConstraint) {
|
||||
final otherTable = await resolveSqlReferenceOrReportError<DriftTable>(
|
||||
constraint.clause.foreignTable.tableName,
|
||||
|
@ -325,6 +342,7 @@ class DriftTableResolver extends LocalElementResolver<DiscoveredDriftTable> {
|
|||
tableConstraints: tableConstraints,
|
||||
virtualTableData: virtualTableData,
|
||||
writeDefaultConstraints: false,
|
||||
overrideTableConstraints: sqlTableConstraints,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:sqlparser/sqlparser.dart';
|
||||
|
||||
import '../../utils/entity_reference_sorter.dart';
|
||||
import '../driver/driver.dart';
|
||||
import '../driver/error.dart';
|
||||
import '../driver/state.dart';
|
||||
|
@ -45,7 +46,7 @@ class FileAnalyzer {
|
|||
.whereType<DriftElement>()
|
||||
.followedBy(element.references)
|
||||
.transitiveClosureUnderReferences()
|
||||
.toList();
|
||||
.sortTopologicallyOrElse(driver.backend.log.severe);
|
||||
|
||||
for (final query in element.declaredQueries) {
|
||||
final engine =
|
||||
|
|
|
@ -11,7 +11,7 @@ class FileAnalysisResult {
|
|||
}
|
||||
|
||||
class ResolvedDatabaseAccessor {
|
||||
final Map<String, SqlQuery> definedQueries;
|
||||
Map<String, SqlQuery> definedQueries;
|
||||
final List<FileState> knownImports;
|
||||
final List<DriftElement> availableElements;
|
||||
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
import 'package:drift_dev/moor_generator.dart';
|
||||
import 'package:drift_dev/src/analyzer/errors.dart';
|
||||
|
||||
/// Transforms queries accessible to the [accessor] so that they use custom
|
||||
/// result names.
|
||||
///
|
||||
/// The "custom result class name" feature can be used to change the name of a
|
||||
/// result class and to generate the same result class for multiple custom
|
||||
/// queries.
|
||||
///
|
||||
/// Merging result classes of queries will always happen from the point of a
|
||||
/// database class or dao. This means that incompatible queries can have the
|
||||
/// same result class name as long as they're not imported into the same moor
|
||||
/// accessor.
|
||||
///
|
||||
/// This feature doesn't work when we apply other simplifications to query, so
|
||||
/// we report an error if the query returns a single column or if it has a
|
||||
/// matching table. This restriction might be lifted in the future, but it makes
|
||||
/// the implementation easier.
|
||||
class CustomResultClassTransformer {
|
||||
final BaseDriftAccessor accessor;
|
||||
|
||||
CustomResultClassTransformer(this.accessor);
|
||||
|
||||
void transform(ErrorSink errors) {
|
||||
// For efficient replacing later on
|
||||
final indexOfOldQueries = <SqlSelectQuery, int>{};
|
||||
final queryGroups = <String, List<SqlSelectQuery>>{};
|
||||
|
||||
// Find and group queries with the same result class name
|
||||
var index = 0;
|
||||
for (final query in accessor.queries ?? const <Never>[]) {
|
||||
final indexOfQuery = index++;
|
||||
|
||||
if (query is! SqlSelectQuery) continue;
|
||||
final selectQuery = query;
|
||||
|
||||
// Doesn't use a custom result class, so it's not affected by this
|
||||
if (selectQuery.requestedResultClass == null) continue;
|
||||
|
||||
// Alright, the query wants a custom result class, but is it allowed to
|
||||
// have one?
|
||||
if (selectQuery.resultSet.singleColumn) {
|
||||
errors.report(ErrorInDartCode(
|
||||
message: "The query ${selectQuery.name} can't have a custom name as "
|
||||
'it only returns one column.',
|
||||
affectedElement: accessor.declaration?.element,
|
||||
));
|
||||
continue;
|
||||
}
|
||||
if (selectQuery.resultSet.matchingTable != null) {
|
||||
errors.report(ErrorInDartCode(
|
||||
message: "The query ${selectQuery.name} can't have a custom name as "
|
||||
'it returns a single table data class.',
|
||||
affectedElement: accessor.declaration?.element,
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
// query will be replaced, save index for fast replacement later on
|
||||
indexOfOldQueries[selectQuery] = indexOfQuery;
|
||||
if (selectQuery.requestedResultClass != null) {
|
||||
queryGroups
|
||||
.putIfAbsent(selectQuery.requestedResultClass!, () => [])
|
||||
.add(selectQuery);
|
||||
}
|
||||
}
|
||||
|
||||
for (final group in queryGroups.entries) {
|
||||
final resultSetName = group.key;
|
||||
final queries = group.value;
|
||||
|
||||
if (!_resultSetsCompatible(queries.map((e) => e.resultSet))) {
|
||||
errors.report(ErrorInDartCode(
|
||||
message: 'Could not merge result sets to $resultSetName: The queries '
|
||||
'have different columns and types.',
|
||||
affectedElement: accessor.declaration?.element,
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
final referenceResult = queries.first.resultSet;
|
||||
final dartNames = {
|
||||
for (final column in referenceResult.columns)
|
||||
column: referenceResult.dartNameFor(column),
|
||||
};
|
||||
|
||||
var isFirst = true;
|
||||
for (final query in queries) {
|
||||
final newResultSet = InferredResultSet(
|
||||
null,
|
||||
query.resultSet.columns,
|
||||
resultClassName: resultSetName,
|
||||
nestedResults: query.resultSet.nestedResults,
|
||||
// Only generate a result class for the first query in the group
|
||||
dontGenerateResultClass: !isFirst,
|
||||
);
|
||||
|
||||
// Make sure compatible columns in the two result sets have the same
|
||||
// Dart name.
|
||||
newResultSet.forceDartNames({
|
||||
for (final entry in dartNames.entries)
|
||||
newResultSet.columns.singleWhere((e) => e.compatibleTo(entry.key)):
|
||||
entry.value,
|
||||
});
|
||||
|
||||
final newQuery = query.replaceResultSet(newResultSet);
|
||||
accessor.queries![indexOfOldQueries[query]!] = newQuery;
|
||||
|
||||
isFirst = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool _resultSetsCompatible(Iterable<InferredResultSet> resultSets) {
|
||||
InferredResultSet? last;
|
||||
|
||||
for (final current in resultSets) {
|
||||
if (last != null && !last.isCompatibleTo(current)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
last = current;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:build/build.dart';
|
||||
import 'package:dart_style/dart_style.dart';
|
||||
|
||||
import '../../analysis/custom_result_class.dart';
|
||||
import '../../analysis/driver/driver.dart';
|
||||
import '../../analysis/driver/error.dart';
|
||||
import '../../analysis/driver/state.dart';
|
||||
import '../../analysis/results/results.dart';
|
||||
import '../../analyzer/options.dart';
|
||||
|
@ -107,7 +109,7 @@ class DriftBuilder extends Builder {
|
|||
|
||||
if (result is BaseDriftAccessor) {
|
||||
final resolved = fileResult.fileAnalysis!.resolvedDatabases[result.id]!;
|
||||
final importedQueries = <DefinedSqlQuery, SqlQuery>{};
|
||||
var importedQueries = <DefinedSqlQuery, SqlQuery>{};
|
||||
|
||||
for (final query
|
||||
in resolved.availableElements.whereType<DefinedSqlQuery>()) {
|
||||
|
@ -120,6 +122,16 @@ class DriftBuilder extends Builder {
|
|||
}
|
||||
}
|
||||
|
||||
// Apply custom result classes
|
||||
final mappedQueries = transformCustomResultClasses(
|
||||
resolved.definedQueries.values.followedBy(importedQueries.values),
|
||||
(message) => log.warning('For accessor ${result.id.name}: $message'),
|
||||
);
|
||||
importedQueries =
|
||||
importedQueries.map((k, v) => MapEntry(k, mappedQueries[v] ?? v));
|
||||
resolved.definedQueries = resolved.definedQueries
|
||||
.map((k, v) => MapEntry(k, mappedQueries[v] ?? v));
|
||||
|
||||
if (result is DriftDatabase) {
|
||||
final input =
|
||||
DatabaseGenerationInput(result, resolved, importedQueries);
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import 'package:drift/drift.dart' hide DriftDatabase;
|
||||
import 'package:sqlparser/sqlparser.dart';
|
||||
|
||||
import '../analysis/results/file_results.dart';
|
||||
import '../analysis/results/results.dart';
|
||||
|
||||
class FindStreamUpdateRules {
|
||||
final DriftDatabase db;
|
||||
final ResolvedDatabaseAccessor db;
|
||||
|
||||
FindStreamUpdateRules(this.db);
|
||||
|
||||
StreamQueryUpdateRules identifyRules() {
|
||||
final rules = <UpdateRule>[];
|
||||
|
||||
for (final entity in db.references) {
|
||||
for (final entity in db.availableElements) {
|
||||
if (entity is DriftTrigger) {
|
||||
_writeRulesForTrigger(entity, rules);
|
||||
} else if (entity is DriftTable) {
|
||||
|
|
|
@ -1,42 +1,71 @@
|
|||
import '../analysis/results/results.dart';
|
||||
|
||||
/// Topologically sorts a list of [DriftElement]s by their
|
||||
/// [DriftElement.references] relationship: Tables appearing first in the
|
||||
/// output have to be created first so the table creation script doesn't crash
|
||||
/// because of tables not existing.
|
||||
///
|
||||
/// If there is a circular reference between [DriftTable]s, an error will
|
||||
/// be added that contains the name of the tables in question. Self-references
|
||||
/// in tables are allowed.
|
||||
List<DriftElement> sortEntitiesTopologically(Iterable<DriftElement> tables) {
|
||||
final run = _SortRun();
|
||||
extension SortTopologically on Iterable<DriftElement> {
|
||||
/// Topologically sorts a list of [DriftElement]s by their
|
||||
/// [DriftElement.references] relationship: Tables appearing first in the
|
||||
/// output have to be created first so the table creation script doesn't crash
|
||||
/// because of tables not existing.
|
||||
///
|
||||
/// If there is a circular reference between [DriftTable]s, an error will
|
||||
/// be added that contains the name of the tables in question.
|
||||
///
|
||||
/// Note that self-references (e.g. a foreign column in a table referencing
|
||||
/// itself or another column in the same table) are _not_ included in
|
||||
/// [DriftElement.references]. For example, an element created for the
|
||||
/// statement `CREATE TABLE pairs (id INTEGER PRIMARY KEY, partner INTEGER
|
||||
/// REFERENCES pairs (id))` has no references in the drift element model.
|
||||
List<DriftElement> sortTopologically() {
|
||||
final run = _SortRun();
|
||||
|
||||
for (final entity in tables) {
|
||||
if (!run.didVisitAlready(entity)) {
|
||||
run.previous[entity] = null;
|
||||
_visit(entity, run);
|
||||
for (final entity in this) {
|
||||
if (!run.didVisitAlready(entity)) {
|
||||
run.previous[entity] = null;
|
||||
_visit(entity, run);
|
||||
}
|
||||
}
|
||||
|
||||
return run.result;
|
||||
}
|
||||
|
||||
/// Sorts elements topologically (like [sortTopologically]).
|
||||
///
|
||||
/// Unlike throwing an exception for circular references, the [reportError]
|
||||
/// callback is invoked and the elements are returned unchanged.
|
||||
List<DriftElement> sortTopologicallyOrElse(
|
||||
void Function(String) reportError) {
|
||||
try {
|
||||
return sortTopologically();
|
||||
} on CircularReferenceException catch (e) {
|
||||
final joined = e.affected.map((e) => e.id.name).join('->');
|
||||
final last = e.affected.last.id.name;
|
||||
final message =
|
||||
'Illegal circular reference. This is likely a bug in drift, '
|
||||
'generated code may be invalid. Invalid cycle from $joined->$last.';
|
||||
reportError(message);
|
||||
|
||||
return toList();
|
||||
}
|
||||
}
|
||||
|
||||
return run.result;
|
||||
}
|
||||
static void _visit(DriftElement entity, _SortRun run) {
|
||||
for (final reference in entity.references) {
|
||||
assert(reference != entity, 'Illegal self-reference in $entity');
|
||||
|
||||
void _visit(DriftElement entity, _SortRun run) {
|
||||
for (final reference in entity.references) {
|
||||
if (run.result.contains(reference) || reference == entity) {
|
||||
// When the target entity has already been added there's nothing to do.
|
||||
// We also ignore self-references
|
||||
} else if (run.previous.containsKey(reference)) {
|
||||
// that's a circular reference, report
|
||||
run.throwCircularException(entity, reference);
|
||||
} else {
|
||||
run.previous[reference] = entity;
|
||||
_visit(reference, run);
|
||||
if (run.result.contains(reference)) {
|
||||
// When the target entity has already been added there's nothing to do.
|
||||
// We also ignore self-references
|
||||
} else if (run.previous.containsKey(reference)) {
|
||||
// that's a circular reference, report
|
||||
run.throwCircularException(entity, reference);
|
||||
} else {
|
||||
run.previous[reference] = entity;
|
||||
_visit(reference, run);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now that everything this table references is written, add the table itself
|
||||
run.result.add(entity);
|
||||
// now that everything this table references is written, add the table itself
|
||||
run.result.add(entity);
|
||||
}
|
||||
}
|
||||
|
||||
class _SortRun {
|
||||
|
@ -73,8 +102,8 @@ class _SortRun {
|
|||
}
|
||||
}
|
||||
|
||||
/// Thrown by [sortEntitiesTopologically] when the graph formed by
|
||||
/// [DriftElement.references] is not acyclic except for self-references.
|
||||
/// Thrown by [SortTopologically] when the graph formed by
|
||||
/// [DriftElement.references] is not acyclic.
|
||||
class CircularReferenceException implements Exception {
|
||||
/// The list of entities forming a circular reference, so that the first
|
||||
/// entity in this list references the second one and so on. The last entity
|
||||
|
|
|
@ -158,7 +158,8 @@ class DatabaseWriter {
|
|||
// close list literal and allSchemaEntities getter
|
||||
..write('];\n');
|
||||
|
||||
final updateRules = FindStreamUpdateRules(db).identifyRules();
|
||||
final updateRules =
|
||||
FindStreamUpdateRules(input.resolvedAccessor).identifyRules();
|
||||
if (updateRules.rules.isNotEmpty) {
|
||||
schemaScope
|
||||
..write('@override\nStreamQueryUpdateRules get streamUpdateRules => ')
|
||||
|
@ -240,13 +241,14 @@ extension on drift.TableUpdate {
|
|||
void writeConstructor(TextEmitter emitter) {
|
||||
emitter
|
||||
..writeDriftRef('TableUpdate')
|
||||
..write('(${asDartLiteral(table)})');
|
||||
..write('(${asDartLiteral(table)}');
|
||||
|
||||
if (kind == null) {
|
||||
emitter.write(')');
|
||||
} else {
|
||||
emitter.write(', kind: ');
|
||||
kind!.write(emitter);
|
||||
emitter.write(')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +264,7 @@ extension on drift.TableUpdateQuery {
|
|||
emitter.write('.onTableName(${asDartLiteral(query.table)} ');
|
||||
|
||||
if (query.limitUpdateKind != null) {
|
||||
emitter.write(', ');
|
||||
emitter.write(', limitUpdateKind: ');
|
||||
query.limitUpdateKind!.write(emitter);
|
||||
}
|
||||
emitter.write(')');
|
||||
|
|
Loading…
Reference in New Issue