Merge branch 'develop' into delightful-queries

This commit is contained in:
Simon Binder 2019-06-16 14:52:49 +02:00
commit 2a5ede1c04
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
11 changed files with 302 additions and 68 deletions

View File

@ -27,7 +27,7 @@ part 'filename.g.dart';
// be represented by a class called "Todo".
class Todos extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text().withLength(min: 6, max: 10)();
TextColumn get title => text().withLength(min: 6, max: 32)();
TextColumn get content => text().named('body')();
IntColumn get category => integer().nullable()();
}

View File

@ -64,6 +64,7 @@ class $CategoriesTable extends Categories
final GeneratedDatabase _db;
final String _alias;
$CategoriesTable(this._db, [this._alias]);
final VerificationMeta _idMeta = const VerificationMeta('id');
GeneratedIntColumn _id;
@override
GeneratedIntColumn get id => _id ??= _constructId();
@ -71,6 +72,8 @@ class $CategoriesTable extends Categories
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
final VerificationMeta _descriptionMeta =
const VerificationMeta('description');
GeneratedTextColumn _description;
@override
GeneratedTextColumn get description =>
@ -92,9 +95,14 @@ class $CategoriesTable extends Categories
@override
final String actualTableName = 'categories';
@override
bool validateIntegrity(Category instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
description.isAcceptableValue(instance.description, isInserting);
VerificationContext validateIntegrity(Category instance, bool isInserting) =>
VerificationContext()
..handle(
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
..handle(
_descriptionMeta,
description.isAcceptableValue(
instance.description, isInserting, _descriptionMeta));
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
@ -199,6 +207,7 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
final GeneratedDatabase _db;
final String _alias;
$RecipesTable(this._db, [this._alias]);
final VerificationMeta _idMeta = const VerificationMeta('id');
GeneratedIntColumn _id;
@override
GeneratedIntColumn get id => _id ??= _constructId();
@ -206,6 +215,7 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
final VerificationMeta _titleMeta = const VerificationMeta('title');
GeneratedTextColumn _title;
@override
GeneratedTextColumn get title => _title ??= _constructTitle();
@ -213,6 +223,8 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
return GeneratedTextColumn('title', $tableName, false, maxTextLength: 16);
}
final VerificationMeta _instructionsMeta =
const VerificationMeta('instructions');
GeneratedTextColumn _instructions;
@override
GeneratedTextColumn get instructions =>
@ -225,6 +237,7 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
);
}
final VerificationMeta _categoryMeta = const VerificationMeta('category');
GeneratedIntColumn _category;
@override
GeneratedIntColumn get category => _category ??= _constructCategory();
@ -245,11 +258,20 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
@override
final String actualTableName = 'recipes';
@override
bool validateIntegrity(Recipe instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
title.isAcceptableValue(instance.title, isInserting) &&
instructions.isAcceptableValue(instance.instructions, isInserting) &&
category.isAcceptableValue(instance.category, isInserting);
VerificationContext validateIntegrity(Recipe instance, bool isInserting) =>
VerificationContext()
..handle(
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
..handle(_titleMeta,
title.isAcceptableValue(instance.title, isInserting, _titleMeta))
..handle(
_instructionsMeta,
instructions.isAcceptableValue(
instance.instructions, isInserting, _instructionsMeta))
..handle(
_categoryMeta,
category.isAcceptableValue(
instance.category, isInserting, _categoryMeta));
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
@ -349,6 +371,7 @@ class $IngredientsTable extends Ingredients
final GeneratedDatabase _db;
final String _alias;
$IngredientsTable(this._db, [this._alias]);
final VerificationMeta _idMeta = const VerificationMeta('id');
GeneratedIntColumn _id;
@override
GeneratedIntColumn get id => _id ??= _constructId();
@ -356,6 +379,7 @@ class $IngredientsTable extends Ingredients
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
final VerificationMeta _nameMeta = const VerificationMeta('name');
GeneratedTextColumn _name;
@override
GeneratedTextColumn get name => _name ??= _constructName();
@ -367,6 +391,8 @@ class $IngredientsTable extends Ingredients
);
}
final VerificationMeta _caloriesPer100gMeta =
const VerificationMeta('caloriesPer100g');
GeneratedIntColumn _caloriesPer100g;
@override
GeneratedIntColumn get caloriesPer100g =>
@ -388,10 +414,17 @@ class $IngredientsTable extends Ingredients
@override
final String actualTableName = 'ingredients';
@override
bool validateIntegrity(Ingredient instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
name.isAcceptableValue(instance.name, isInserting) &&
caloriesPer100g.isAcceptableValue(instance.caloriesPer100g, isInserting);
VerificationContext validateIntegrity(
Ingredient instance, bool isInserting) =>
VerificationContext()
..handle(
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
..handle(_nameMeta,
name.isAcceptableValue(instance.name, isInserting, _nameMeta))
..handle(
_caloriesPer100gMeta,
caloriesPer100g.isAcceptableValue(
instance.caloriesPer100g, isInserting, _caloriesPer100gMeta));
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
@ -492,6 +525,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
final GeneratedDatabase _db;
final String _alias;
$IngredientInRecipesTable(this._db, [this._alias]);
final VerificationMeta _recipeMeta = const VerificationMeta('recipe');
GeneratedIntColumn _recipe;
@override
GeneratedIntColumn get recipe => _recipe ??= _constructRecipe();
@ -503,6 +537,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
);
}
final VerificationMeta _ingredientMeta = const VerificationMeta('ingredient');
GeneratedIntColumn _ingredient;
@override
GeneratedIntColumn get ingredient => _ingredient ??= _constructIngredient();
@ -514,6 +549,8 @@ class $IngredientInRecipesTable extends IngredientInRecipes
);
}
final VerificationMeta _amountInGramsMeta =
const VerificationMeta('amountInGrams');
GeneratedIntColumn _amountInGrams;
@override
GeneratedIntColumn get amountInGrams =>
@ -535,10 +572,19 @@ class $IngredientInRecipesTable extends IngredientInRecipes
@override
final String actualTableName = 'recipe_ingredients';
@override
bool validateIntegrity(IngredientInRecipe instance, bool isInserting) =>
recipe.isAcceptableValue(instance.recipe, isInserting) &&
ingredient.isAcceptableValue(instance.ingredient, isInserting) &&
amountInGrams.isAcceptableValue(instance.amountInGrams, isInserting);
VerificationContext validateIntegrity(
IngredientInRecipe instance, bool isInserting) =>
VerificationContext()
..handle(_recipeMeta,
recipe.isAcceptableValue(instance.recipe, isInserting, _recipeMeta))
..handle(
_ingredientMeta,
ingredient.isAcceptableValue(
instance.ingredient, isInserting, _ingredientMeta))
..handle(
_amountInGramsMeta,
amountInGrams.isAcceptableValue(
instance.amountInGrams, isInserting, _amountInGramsMeta));
@override
Set<GeneratedColumn> get $primaryKey => {recipe, ingredient};
@override

View File

@ -21,6 +21,7 @@ export 'package:moor/src/runtime/statements/select.dart';
export 'package:moor/src/runtime/statements/insert.dart';
export 'package:moor/src/runtime/statements/delete.dart';
export 'package:moor/src/runtime/structure/columns.dart';
export 'package:moor/src/runtime/structure/error_handling.dart';
export 'package:moor/src/runtime/structure/table_info.dart';
export 'package:moor/src/runtime/data_class.dart';
export 'package:moor/src/runtime/database.dart';

View File

@ -116,9 +116,7 @@ class InsertStatement<DataClass> {
throw InvalidDataException(
'Cannot writee null row into ${table.$tableName}');
}
if (!table.validateIntegrity(d, true)) {
throw InvalidDataException(
'Invalid data: $d cannot be written into ${table.$tableName}');
}
table.validateIntegrity(d, true).throwIfInvalid(d);
}
}

View File

@ -56,10 +56,7 @@ class UpdateStatement<T extends Table, D> extends Query<T, D>
/// See also: [replace], which does not require [where] statements and
/// supports setting fields back to null.
Future<int> write(D entity) async {
if (!table.validateIntegrity(entity, false)) {
throw InvalidDataException(
'Invalid data: $entity cannot be written into ${table.$tableName}');
}
table.validateIntegrity(entity, false).throwIfInvalid(entity);
_updatedFields = table.entityToSql(entity)
..remove((_, value) => value == null);
@ -93,10 +90,7 @@ class UpdateStatement<T extends Table, D> extends Query<T, D>
// because all the fields from the entity will be written (as opposed to a
// regular update, where only non-null fields will be written). If isInserted
// was false, the null fields would not be validated.
if (!table.validateIntegrity(entity, true)) {
throw InvalidDataException('Invalid data: $entity cannot be used to '
'replace another row as some required fields are null or invalid.');
}
table.validateIntegrity(entity, true).throwIfInvalid(entity);
assert(
whereExpr == null,
'When using replace on an update statement, you may not use where(...)'

View File

@ -9,6 +9,12 @@ import 'package:moor/src/runtime/expressions/variables.dart';
import 'package:moor/src/types/sql_types.dart';
import 'package:moor/sqlite_keywords.dart';
import 'error_handling.dart';
const VerificationResult _invalidNull = VerificationResult.failure(
"This column is not nullable and doesn't have a default value. "
"Null fields thus can't be inserted.");
/// Base class for the implementation of [Column].
abstract class GeneratedColumn<T, S extends SqlType<T>> extends Column<T, S> {
/// The sql name of this column.
@ -84,9 +90,14 @@ abstract class GeneratedColumn<T, S extends SqlType<T>> extends Column<T, S> {
/// method should check whether the value is valid for an update. Null values
/// should always be accepted for updates, as the describe a value that should
/// not be replaced.
bool isAcceptableValue(T value, bool duringInsert) {
VerificationResult isAcceptableValue(
T value, bool duringInsert, VerificationMeta meta) {
final nullOk = !duringInsert || $nullable || defaultValue != null;
return nullOk || value != null;
if (!nullOk && value == null) {
return _invalidNull;
} else {
return const VerificationResult.success();
}
}
}
@ -114,15 +125,22 @@ class GeneratedTextColumn extends GeneratedColumn<String, StringType>
final String typeName = 'VARCHAR';
@override
bool isAcceptableValue(String value, bool duringInsert) {
VerificationResult isAcceptableValue(
String value, bool duringInsert, VerificationMeta meta) {
// handle nullability check in common column
if (value == null) return super.isAcceptableValue(null, duringInsert);
if (value == null) return super.isAcceptableValue(null, duringInsert, meta);
final length = value.length;
if (minTextLength != null && minTextLength > length) return false;
if (maxTextLength != null && maxTextLength < length) return false;
if (minTextLength != null && minTextLength > length) {
return VerificationResult.failure(
'Must at least be $minTextLength characters long.');
}
if (maxTextLength != null && maxTextLength < length) {
return VerificationResult.failure(
'Must at most be $maxTextLength characters long.');
}
return true;
return const VerificationResult.success();
}
}
@ -171,8 +189,13 @@ class GeneratedIntColumn extends GeneratedColumn<int, IntType>
}
@override
bool isAcceptableValue(int value, bool duringInsert) =>
hasAutoIncrement || super.isAcceptableValue(value, duringInsert);
VerificationResult isAcceptableValue(
int value, bool duringInsert, VerificationMeta meta) {
if (hasAutoIncrement) {
return const VerificationResult.success();
}
return super.isAcceptableValue(value, duringInsert, meta);
}
}
class GeneratedDateTimeColumn extends GeneratedColumn<DateTime, DateTimeType>

View File

@ -0,0 +1,48 @@
import 'package:moor/moor.dart';
/// Additional information that is passed to [GeneratedColumn]s when verifying
/// data to provide more helpful error messages.
class VerificationMeta {
/// The dart getter name of the property being validated.
final String dartGetterName;
const VerificationMeta(this.dartGetterName);
}
/// Returned by [GeneratedColumn.isAcceptableValue] to provide a description
/// when a valid is invalid.
class VerificationResult {
final bool success;
final String message;
const VerificationResult(this.success, this.message);
const VerificationResult.success()
: success = true,
message = null;
const VerificationResult.failure(this.message) : success = false;
}
class VerificationContext {
final Map<VerificationMeta, VerificationResult> _errors = {};
bool get dataValid => _errors.isEmpty;
void handle(VerificationMeta meta, VerificationResult result) {
if (!result.success) {
_errors[meta] = result;
}
}
void throwIfInvalid(dynamic dataObject) {
if (dataValid) return;
final messageBuilder =
StringBuffer('Sorry, $dataObject cannot be used for that because: \n');
_errors.forEach((meta, result) {
messageBuilder.write('${meta.dartGetterName}: ${result.message}\n');
});
throw InvalidDataException(messageBuilder.toString());
}
}

View File

@ -38,7 +38,7 @@ mixin TableInfo<TableDsl extends Table, DataClass> {
/// that it respects all constraints (nullability, text length, etc.).
/// During insertion mode, fields that have a default value or are
/// auto-incrementing are allowed to be null as they will be set by sqlite.
bool validateIntegrity(DataClass instance, bool isInserting);
VerificationContext validateIntegrity(DataClass instance, bool isInserting);
/// Maps the given data class to a [Map] that can be inserted into sql. The
/// keys should represent the column name in sql, the values the corresponding

View File

@ -102,6 +102,7 @@ class $TodosTableTable extends TodosTable
final GeneratedDatabase _db;
final String _alias;
$TodosTableTable(this._db, [this._alias]);
final VerificationMeta _idMeta = const VerificationMeta('id');
GeneratedIntColumn _id;
@override
GeneratedIntColumn get id => _id ??= _constructId();
@ -109,6 +110,7 @@ class $TodosTableTable extends TodosTable
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
final VerificationMeta _titleMeta = const VerificationMeta('title');
GeneratedTextColumn _title;
@override
GeneratedTextColumn get title => _title ??= _constructTitle();
@ -117,6 +119,7 @@ class $TodosTableTable extends TodosTable
minTextLength: 4, maxTextLength: 16);
}
final VerificationMeta _contentMeta = const VerificationMeta('content');
GeneratedTextColumn _content;
@override
GeneratedTextColumn get content => _content ??= _constructContent();
@ -128,6 +131,7 @@ class $TodosTableTable extends TodosTable
);
}
final VerificationMeta _targetDateMeta = const VerificationMeta('targetDate');
GeneratedDateTimeColumn _targetDate;
@override
GeneratedDateTimeColumn get targetDate =>
@ -140,6 +144,7 @@ class $TodosTableTable extends TodosTable
);
}
final VerificationMeta _categoryMeta = const VerificationMeta('category');
GeneratedIntColumn _category;
@override
GeneratedIntColumn get category => _category ??= _constructCategory();
@ -161,12 +166,24 @@ class $TodosTableTable extends TodosTable
@override
final String actualTableName = 'todos';
@override
bool validateIntegrity(TodoEntry instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
title.isAcceptableValue(instance.title, isInserting) &&
content.isAcceptableValue(instance.content, isInserting) &&
targetDate.isAcceptableValue(instance.targetDate, isInserting) &&
category.isAcceptableValue(instance.category, isInserting);
VerificationContext validateIntegrity(TodoEntry instance, bool isInserting) =>
VerificationContext()
..handle(
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
..handle(_titleMeta,
title.isAcceptableValue(instance.title, isInserting, _titleMeta))
..handle(
_contentMeta,
content.isAcceptableValue(
instance.content, isInserting, _contentMeta))
..handle(
_targetDateMeta,
targetDate.isAcceptableValue(
instance.targetDate, isInserting, _targetDateMeta))
..handle(
_categoryMeta,
category.isAcceptableValue(
instance.category, isInserting, _categoryMeta));
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
@ -259,6 +276,7 @@ class $CategoriesTable extends Categories
final GeneratedDatabase _db;
final String _alias;
$CategoriesTable(this._db, [this._alias]);
final VerificationMeta _idMeta = const VerificationMeta('id');
GeneratedIntColumn _id;
@override
GeneratedIntColumn get id => _id ??= _constructId();
@ -266,6 +284,8 @@ class $CategoriesTable extends Categories
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
final VerificationMeta _descriptionMeta =
const VerificationMeta('description');
GeneratedTextColumn _description;
@override
GeneratedTextColumn get description =>
@ -284,9 +304,14 @@ class $CategoriesTable extends Categories
@override
final String actualTableName = 'categories';
@override
bool validateIntegrity(Category instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
description.isAcceptableValue(instance.description, isInserting);
VerificationContext validateIntegrity(Category instance, bool isInserting) =>
VerificationContext()
..handle(
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
..handle(
_descriptionMeta,
description.isAcceptableValue(
instance.description, isInserting, _descriptionMeta));
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
@ -413,6 +438,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
final GeneratedDatabase _db;
final String _alias;
$UsersTable(this._db, [this._alias]);
final VerificationMeta _idMeta = const VerificationMeta('id');
GeneratedIntColumn _id;
@override
GeneratedIntColumn get id => _id ??= _constructId();
@ -420,6 +446,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
}
final VerificationMeta _nameMeta = const VerificationMeta('name');
GeneratedTextColumn _name;
@override
GeneratedTextColumn get name => _name ??= _constructName();
@ -428,6 +455,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
minTextLength: 6, maxTextLength: 32);
}
final VerificationMeta _isAwesomeMeta = const VerificationMeta('isAwesome');
GeneratedBoolColumn _isAwesome;
@override
GeneratedBoolColumn get isAwesome => _isAwesome ??= _constructIsAwesome();
@ -436,6 +464,8 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
defaultValue: const Constant(true));
}
final VerificationMeta _profilePictureMeta =
const VerificationMeta('profilePicture');
GeneratedBlobColumn _profilePicture;
@override
GeneratedBlobColumn get profilePicture =>
@ -448,6 +478,8 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
);
}
final VerificationMeta _creationTimeMeta =
const VerificationMeta('creationTime');
GeneratedDateTimeColumn _creationTime;
@override
GeneratedDateTimeColumn get creationTime =>
@ -467,12 +499,24 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
@override
final String actualTableName = 'users';
@override
bool validateIntegrity(User instance, bool isInserting) =>
id.isAcceptableValue(instance.id, isInserting) &&
name.isAcceptableValue(instance.name, isInserting) &&
isAwesome.isAcceptableValue(instance.isAwesome, isInserting) &&
profilePicture.isAcceptableValue(instance.profilePicture, isInserting) &&
creationTime.isAcceptableValue(instance.creationTime, isInserting);
VerificationContext validateIntegrity(User instance, bool isInserting) =>
VerificationContext()
..handle(
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
..handle(_nameMeta,
name.isAcceptableValue(instance.name, isInserting, _nameMeta))
..handle(
_isAwesomeMeta,
isAwesome.isAcceptableValue(
instance.isAwesome, isInserting, _isAwesomeMeta))
..handle(
_profilePictureMeta,
profilePicture.isAcceptableValue(
instance.profilePicture, isInserting, _profilePictureMeta))
..handle(
_creationTimeMeta,
creationTime.isAcceptableValue(
instance.creationTime, isInserting, _creationTimeMeta));
@override
Set<GeneratedColumn> get $primaryKey => {id};
@override
@ -563,6 +607,7 @@ class $SharedTodosTable extends SharedTodos
final GeneratedDatabase _db;
final String _alias;
$SharedTodosTable(this._db, [this._alias]);
final VerificationMeta _todoMeta = const VerificationMeta('todo');
GeneratedIntColumn _todo;
@override
GeneratedIntColumn get todo => _todo ??= _constructTodo();
@ -574,6 +619,7 @@ class $SharedTodosTable extends SharedTodos
);
}
final VerificationMeta _userMeta = const VerificationMeta('user');
GeneratedIntColumn _user;
@override
GeneratedIntColumn get user => _user ??= _constructUser();
@ -594,9 +640,13 @@ class $SharedTodosTable extends SharedTodos
@override
final String actualTableName = 'shared_todos';
@override
bool validateIntegrity(SharedTodo instance, bool isInserting) =>
todo.isAcceptableValue(instance.todo, isInserting) &&
user.isAcceptableValue(instance.user, isInserting);
VerificationContext validateIntegrity(
SharedTodo instance, bool isInserting) =>
VerificationContext()
..handle(_todoMeta,
todo.isAcceptableValue(instance.todo, isInserting, _todoMeta))
..handle(_userMeta,
user.isAcceptableValue(instance.user, isInserting, _userMeta));
@override
Set<GeneratedColumn> get $primaryKey => {todo, user};
@override
@ -686,6 +736,8 @@ class $TableWithoutPKTable extends TableWithoutPK
final GeneratedDatabase _db;
final String _alias;
$TableWithoutPKTable(this._db, [this._alias]);
final VerificationMeta _notReallyAnIdMeta =
const VerificationMeta('notReallyAnId');
GeneratedIntColumn _notReallyAnId;
@override
GeneratedIntColumn get notReallyAnId =>
@ -698,6 +750,7 @@ class $TableWithoutPKTable extends TableWithoutPK
);
}
final VerificationMeta _someFloatMeta = const VerificationMeta('someFloat');
GeneratedRealColumn _someFloat;
@override
GeneratedRealColumn get someFloat => _someFloat ??= _constructSomeFloat();
@ -718,9 +771,17 @@ class $TableWithoutPKTable extends TableWithoutPK
@override
final String actualTableName = 'table_without_p_k';
@override
bool validateIntegrity(TableWithoutPKData instance, bool isInserting) =>
notReallyAnId.isAcceptableValue(instance.notReallyAnId, isInserting) &&
someFloat.isAcceptableValue(instance.someFloat, isInserting);
VerificationContext validateIntegrity(
TableWithoutPKData instance, bool isInserting) =>
VerificationContext()
..handle(
_notReallyAnIdMeta,
notReallyAnId.isAcceptableValue(
instance.notReallyAnId, isInserting, _notReallyAnIdMeta))
..handle(
_someFloatMeta,
someFloat.isAcceptableValue(
instance.someFloat, isInserting, _someFloatMeta));
@override
Set<GeneratedColumn> get $primaryKey => <GeneratedColumn>{};
@override

View File

@ -0,0 +1,42 @@
import 'package:moor/moor.dart';
import 'package:test_api/test_api.dart';
import 'data/tables/todos.dart';
import 'data/utils/mocks.dart';
// the content is set to non-null and the title must be between 4 and 16 chars
// long
final nullContent = TodoEntry(title: 'Test', content: null);
final shortTitle = TodoEntry(title: 'A', content: 'content');
final longTitle = TodoEntry(title: 'A ${'very' * 5} long title', content: 'hi');
final valid = TodoEntry(title: 'Test', content: 'Some content');
void main() {
TodoDb db;
MockExecutor executor;
setUp(() {
executor = MockExecutor();
db = TodoDb(executor);
});
test('detects errors on insert', () {
expect(
() => db.into(db.todosTable).insert(nullContent),
throwsA(predicate<InvalidDataException>(
(e) => e.message.contains('not nullable'))),
);
expect(
() => db.into(db.todosTable).insert(shortTitle),
throwsA(predicate<InvalidDataException>(
(e) => e.message.contains('Must at least be'))),
);
expect(
() => db.into(db.todosTable).insert(longTitle),
throwsA(predicate<InvalidDataException>(
(e) => e.message.contains('Must at most be'))),
);
expect(db.into(db.todosTable).insert(valid), completes);
});
}

View File

@ -34,6 +34,7 @@ class TableWriter {
// Generate the columns
for (var column in table.columns) {
_writeColumnVerificationMeta(buffer, column);
_writeColumnGetter(buffer, column);
}
@ -147,22 +148,42 @@ class TableWriter {
);
}
void _writeColumnVerificationMeta(
StringBuffer buffer, SpecifiedColumn column) {
// final VerificationMeta _targetDateMeta = const VerificationMeta('targetDate');
buffer
..write('final VerificationMeta ${_fieldNameForColumnMeta(column)} = ')
..write("const VerificationMeta('${column.dartGetterName}');\n");
}
void _writeValidityCheckMethod(StringBuffer buffer) {
final dataClass = table.dartTypeName;
buffer.write(
'@override\nbool validateIntegrity($dataClass instance, bool isInserting) => ');
buffer.write('@override\nVerificationContext validateIntegrity'
'($dataClass instance, bool isInserting) => VerificationContext()');
final validationCode = table.columns.map((column) {
/*
return VerificationContext()
..handle(
_categoryMeta,
category.isAcceptableValue(
instance.category, isInserting, _categoryMeta));
*/
for (var column in table.columns) {
final getterName = column.dartGetterName;
final metaName = _fieldNameForColumnMeta(column);
// generated columns have a isAcceptableValue(T value, bool duringInsert)
// method
// ..handle(_meta, c.isAcceptableValue(instance.c, insert, _meta))
buffer.write('..handle($metaName, $getterName.isAcceptableValue('
'instance.$getterName, isInserting, $metaName))');
}
return '$getterName.isAcceptableValue(instance.$getterName, isInserting)';
}).join('&&');
buffer.write(';\n');
}
buffer..write(validationCode)..write(';\n');
String _fieldNameForColumnMeta(SpecifiedColumn column) {
return '_${column.dartGetterName}Meta';
}
void _writePrimaryKeyOverride(StringBuffer buffer) {