mirror of https://github.com/AMT-Cheif/drift.git
Merge branch 'develop' into delightful-queries
This commit is contained in:
commit
2a5ede1c04
|
@ -27,7 +27,7 @@ part 'filename.g.dart';
|
||||||
// be represented by a class called "Todo".
|
// be represented by a class called "Todo".
|
||||||
class Todos extends Table {
|
class Todos extends Table {
|
||||||
IntColumn get id => integer().autoIncrement()();
|
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')();
|
TextColumn get content => text().named('body')();
|
||||||
IntColumn get category => integer().nullable()();
|
IntColumn get category => integer().nullable()();
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ class $CategoriesTable extends Categories
|
||||||
final GeneratedDatabase _db;
|
final GeneratedDatabase _db;
|
||||||
final String _alias;
|
final String _alias;
|
||||||
$CategoriesTable(this._db, [this._alias]);
|
$CategoriesTable(this._db, [this._alias]);
|
||||||
|
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||||
GeneratedIntColumn _id;
|
GeneratedIntColumn _id;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get id => _id ??= _constructId();
|
GeneratedIntColumn get id => _id ??= _constructId();
|
||||||
|
@ -71,6 +72,8 @@ class $CategoriesTable extends Categories
|
||||||
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _descriptionMeta =
|
||||||
|
const VerificationMeta('description');
|
||||||
GeneratedTextColumn _description;
|
GeneratedTextColumn _description;
|
||||||
@override
|
@override
|
||||||
GeneratedTextColumn get description =>
|
GeneratedTextColumn get description =>
|
||||||
|
@ -92,9 +95,14 @@ class $CategoriesTable extends Categories
|
||||||
@override
|
@override
|
||||||
final String actualTableName = 'categories';
|
final String actualTableName = 'categories';
|
||||||
@override
|
@override
|
||||||
bool validateIntegrity(Category instance, bool isInserting) =>
|
VerificationContext validateIntegrity(Category instance, bool isInserting) =>
|
||||||
id.isAcceptableValue(instance.id, isInserting) &&
|
VerificationContext()
|
||||||
description.isAcceptableValue(instance.description, isInserting);
|
..handle(
|
||||||
|
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
|
||||||
|
..handle(
|
||||||
|
_descriptionMeta,
|
||||||
|
description.isAcceptableValue(
|
||||||
|
instance.description, isInserting, _descriptionMeta));
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
|
@ -199,6 +207,7 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
||||||
final GeneratedDatabase _db;
|
final GeneratedDatabase _db;
|
||||||
final String _alias;
|
final String _alias;
|
||||||
$RecipesTable(this._db, [this._alias]);
|
$RecipesTable(this._db, [this._alias]);
|
||||||
|
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||||
GeneratedIntColumn _id;
|
GeneratedIntColumn _id;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get id => _id ??= _constructId();
|
GeneratedIntColumn get id => _id ??= _constructId();
|
||||||
|
@ -206,6 +215,7 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
||||||
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _titleMeta = const VerificationMeta('title');
|
||||||
GeneratedTextColumn _title;
|
GeneratedTextColumn _title;
|
||||||
@override
|
@override
|
||||||
GeneratedTextColumn get title => _title ??= _constructTitle();
|
GeneratedTextColumn get title => _title ??= _constructTitle();
|
||||||
|
@ -213,6 +223,8 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
||||||
return GeneratedTextColumn('title', $tableName, false, maxTextLength: 16);
|
return GeneratedTextColumn('title', $tableName, false, maxTextLength: 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _instructionsMeta =
|
||||||
|
const VerificationMeta('instructions');
|
||||||
GeneratedTextColumn _instructions;
|
GeneratedTextColumn _instructions;
|
||||||
@override
|
@override
|
||||||
GeneratedTextColumn get instructions =>
|
GeneratedTextColumn get instructions =>
|
||||||
|
@ -225,6 +237,7 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _categoryMeta = const VerificationMeta('category');
|
||||||
GeneratedIntColumn _category;
|
GeneratedIntColumn _category;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get category => _category ??= _constructCategory();
|
GeneratedIntColumn get category => _category ??= _constructCategory();
|
||||||
|
@ -245,11 +258,20 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
||||||
@override
|
@override
|
||||||
final String actualTableName = 'recipes';
|
final String actualTableName = 'recipes';
|
||||||
@override
|
@override
|
||||||
bool validateIntegrity(Recipe instance, bool isInserting) =>
|
VerificationContext validateIntegrity(Recipe instance, bool isInserting) =>
|
||||||
id.isAcceptableValue(instance.id, isInserting) &&
|
VerificationContext()
|
||||||
title.isAcceptableValue(instance.title, isInserting) &&
|
..handle(
|
||||||
instructions.isAcceptableValue(instance.instructions, isInserting) &&
|
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
|
||||||
category.isAcceptableValue(instance.category, isInserting);
|
..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
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
|
@ -349,6 +371,7 @@ class $IngredientsTable extends Ingredients
|
||||||
final GeneratedDatabase _db;
|
final GeneratedDatabase _db;
|
||||||
final String _alias;
|
final String _alias;
|
||||||
$IngredientsTable(this._db, [this._alias]);
|
$IngredientsTable(this._db, [this._alias]);
|
||||||
|
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||||
GeneratedIntColumn _id;
|
GeneratedIntColumn _id;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get id => _id ??= _constructId();
|
GeneratedIntColumn get id => _id ??= _constructId();
|
||||||
|
@ -356,6 +379,7 @@ class $IngredientsTable extends Ingredients
|
||||||
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _nameMeta = const VerificationMeta('name');
|
||||||
GeneratedTextColumn _name;
|
GeneratedTextColumn _name;
|
||||||
@override
|
@override
|
||||||
GeneratedTextColumn get name => _name ??= _constructName();
|
GeneratedTextColumn get name => _name ??= _constructName();
|
||||||
|
@ -367,6 +391,8 @@ class $IngredientsTable extends Ingredients
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _caloriesPer100gMeta =
|
||||||
|
const VerificationMeta('caloriesPer100g');
|
||||||
GeneratedIntColumn _caloriesPer100g;
|
GeneratedIntColumn _caloriesPer100g;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get caloriesPer100g =>
|
GeneratedIntColumn get caloriesPer100g =>
|
||||||
|
@ -388,10 +414,17 @@ class $IngredientsTable extends Ingredients
|
||||||
@override
|
@override
|
||||||
final String actualTableName = 'ingredients';
|
final String actualTableName = 'ingredients';
|
||||||
@override
|
@override
|
||||||
bool validateIntegrity(Ingredient instance, bool isInserting) =>
|
VerificationContext validateIntegrity(
|
||||||
id.isAcceptableValue(instance.id, isInserting) &&
|
Ingredient instance, bool isInserting) =>
|
||||||
name.isAcceptableValue(instance.name, isInserting) &&
|
VerificationContext()
|
||||||
caloriesPer100g.isAcceptableValue(instance.caloriesPer100g, isInserting);
|
..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
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
|
@ -492,6 +525,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
||||||
final GeneratedDatabase _db;
|
final GeneratedDatabase _db;
|
||||||
final String _alias;
|
final String _alias;
|
||||||
$IngredientInRecipesTable(this._db, [this._alias]);
|
$IngredientInRecipesTable(this._db, [this._alias]);
|
||||||
|
final VerificationMeta _recipeMeta = const VerificationMeta('recipe');
|
||||||
GeneratedIntColumn _recipe;
|
GeneratedIntColumn _recipe;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get recipe => _recipe ??= _constructRecipe();
|
GeneratedIntColumn get recipe => _recipe ??= _constructRecipe();
|
||||||
|
@ -503,6 +537,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _ingredientMeta = const VerificationMeta('ingredient');
|
||||||
GeneratedIntColumn _ingredient;
|
GeneratedIntColumn _ingredient;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get ingredient => _ingredient ??= _constructIngredient();
|
GeneratedIntColumn get ingredient => _ingredient ??= _constructIngredient();
|
||||||
|
@ -514,6 +549,8 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _amountInGramsMeta =
|
||||||
|
const VerificationMeta('amountInGrams');
|
||||||
GeneratedIntColumn _amountInGrams;
|
GeneratedIntColumn _amountInGrams;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get amountInGrams =>
|
GeneratedIntColumn get amountInGrams =>
|
||||||
|
@ -535,10 +572,19 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
||||||
@override
|
@override
|
||||||
final String actualTableName = 'recipe_ingredients';
|
final String actualTableName = 'recipe_ingredients';
|
||||||
@override
|
@override
|
||||||
bool validateIntegrity(IngredientInRecipe instance, bool isInserting) =>
|
VerificationContext validateIntegrity(
|
||||||
recipe.isAcceptableValue(instance.recipe, isInserting) &&
|
IngredientInRecipe instance, bool isInserting) =>
|
||||||
ingredient.isAcceptableValue(instance.ingredient, isInserting) &&
|
VerificationContext()
|
||||||
amountInGrams.isAcceptableValue(instance.amountInGrams, isInserting);
|
..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
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {recipe, ingredient};
|
Set<GeneratedColumn> get $primaryKey => {recipe, ingredient};
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -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/insert.dart';
|
||||||
export 'package:moor/src/runtime/statements/delete.dart';
|
export 'package:moor/src/runtime/statements/delete.dart';
|
||||||
export 'package:moor/src/runtime/structure/columns.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/structure/table_info.dart';
|
||||||
export 'package:moor/src/runtime/data_class.dart';
|
export 'package:moor/src/runtime/data_class.dart';
|
||||||
export 'package:moor/src/runtime/database.dart';
|
export 'package:moor/src/runtime/database.dart';
|
||||||
|
|
|
@ -116,9 +116,7 @@ class InsertStatement<DataClass> {
|
||||||
throw InvalidDataException(
|
throw InvalidDataException(
|
||||||
'Cannot writee null row into ${table.$tableName}');
|
'Cannot writee null row into ${table.$tableName}');
|
||||||
}
|
}
|
||||||
if (!table.validateIntegrity(d, true)) {
|
|
||||||
throw InvalidDataException(
|
table.validateIntegrity(d, true).throwIfInvalid(d);
|
||||||
'Invalid data: $d cannot be written into ${table.$tableName}');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,10 +56,7 @@ class UpdateStatement<T extends Table, D> extends Query<T, D>
|
||||||
/// See also: [replace], which does not require [where] statements and
|
/// See also: [replace], which does not require [where] statements and
|
||||||
/// supports setting fields back to null.
|
/// supports setting fields back to null.
|
||||||
Future<int> write(D entity) async {
|
Future<int> write(D entity) async {
|
||||||
if (!table.validateIntegrity(entity, false)) {
|
table.validateIntegrity(entity, false).throwIfInvalid(entity);
|
||||||
throw InvalidDataException(
|
|
||||||
'Invalid data: $entity cannot be written into ${table.$tableName}');
|
|
||||||
}
|
|
||||||
|
|
||||||
_updatedFields = table.entityToSql(entity)
|
_updatedFields = table.entityToSql(entity)
|
||||||
..remove((_, value) => value == null);
|
..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
|
// 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
|
// regular update, where only non-null fields will be written). If isInserted
|
||||||
// was false, the null fields would not be validated.
|
// was false, the null fields would not be validated.
|
||||||
if (!table.validateIntegrity(entity, true)) {
|
table.validateIntegrity(entity, true).throwIfInvalid(entity);
|
||||||
throw InvalidDataException('Invalid data: $entity cannot be used to '
|
|
||||||
'replace another row as some required fields are null or invalid.');
|
|
||||||
}
|
|
||||||
assert(
|
assert(
|
||||||
whereExpr == null,
|
whereExpr == null,
|
||||||
'When using replace on an update statement, you may not use where(...)'
|
'When using replace on an update statement, you may not use where(...)'
|
||||||
|
|
|
@ -9,6 +9,12 @@ import 'package:moor/src/runtime/expressions/variables.dart';
|
||||||
import 'package:moor/src/types/sql_types.dart';
|
import 'package:moor/src/types/sql_types.dart';
|
||||||
import 'package:moor/sqlite_keywords.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].
|
/// Base class for the implementation of [Column].
|
||||||
abstract class GeneratedColumn<T, S extends SqlType<T>> extends Column<T, S> {
|
abstract class GeneratedColumn<T, S extends SqlType<T>> extends Column<T, S> {
|
||||||
/// The sql name of this column.
|
/// 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
|
/// 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
|
/// should always be accepted for updates, as the describe a value that should
|
||||||
/// not be replaced.
|
/// not be replaced.
|
||||||
bool isAcceptableValue(T value, bool duringInsert) {
|
VerificationResult isAcceptableValue(
|
||||||
|
T value, bool duringInsert, VerificationMeta meta) {
|
||||||
final nullOk = !duringInsert || $nullable || defaultValue != null;
|
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';
|
final String typeName = 'VARCHAR';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool isAcceptableValue(String value, bool duringInsert) {
|
VerificationResult isAcceptableValue(
|
||||||
|
String value, bool duringInsert, VerificationMeta meta) {
|
||||||
// handle nullability check in common column
|
// 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;
|
final length = value.length;
|
||||||
if (minTextLength != null && minTextLength > length) return false;
|
if (minTextLength != null && minTextLength > length) {
|
||||||
if (maxTextLength != null && maxTextLength < length) return false;
|
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
|
@override
|
||||||
bool isAcceptableValue(int value, bool duringInsert) =>
|
VerificationResult isAcceptableValue(
|
||||||
hasAutoIncrement || super.isAcceptableValue(value, duringInsert);
|
int value, bool duringInsert, VerificationMeta meta) {
|
||||||
|
if (hasAutoIncrement) {
|
||||||
|
return const VerificationResult.success();
|
||||||
|
}
|
||||||
|
return super.isAcceptableValue(value, duringInsert, meta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeneratedDateTimeColumn extends GeneratedColumn<DateTime, DateTimeType>
|
class GeneratedDateTimeColumn extends GeneratedColumn<DateTime, DateTimeType>
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,7 @@ mixin TableInfo<TableDsl extends Table, DataClass> {
|
||||||
/// that it respects all constraints (nullability, text length, etc.).
|
/// that it respects all constraints (nullability, text length, etc.).
|
||||||
/// During insertion mode, fields that have a default value or are
|
/// 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.
|
/// 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
|
/// 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
|
/// keys should represent the column name in sql, the values the corresponding
|
||||||
|
|
|
@ -102,6 +102,7 @@ class $TodosTableTable extends TodosTable
|
||||||
final GeneratedDatabase _db;
|
final GeneratedDatabase _db;
|
||||||
final String _alias;
|
final String _alias;
|
||||||
$TodosTableTable(this._db, [this._alias]);
|
$TodosTableTable(this._db, [this._alias]);
|
||||||
|
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||||
GeneratedIntColumn _id;
|
GeneratedIntColumn _id;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get id => _id ??= _constructId();
|
GeneratedIntColumn get id => _id ??= _constructId();
|
||||||
|
@ -109,6 +110,7 @@ class $TodosTableTable extends TodosTable
|
||||||
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _titleMeta = const VerificationMeta('title');
|
||||||
GeneratedTextColumn _title;
|
GeneratedTextColumn _title;
|
||||||
@override
|
@override
|
||||||
GeneratedTextColumn get title => _title ??= _constructTitle();
|
GeneratedTextColumn get title => _title ??= _constructTitle();
|
||||||
|
@ -117,6 +119,7 @@ class $TodosTableTable extends TodosTable
|
||||||
minTextLength: 4, maxTextLength: 16);
|
minTextLength: 4, maxTextLength: 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _contentMeta = const VerificationMeta('content');
|
||||||
GeneratedTextColumn _content;
|
GeneratedTextColumn _content;
|
||||||
@override
|
@override
|
||||||
GeneratedTextColumn get content => _content ??= _constructContent();
|
GeneratedTextColumn get content => _content ??= _constructContent();
|
||||||
|
@ -128,6 +131,7 @@ class $TodosTableTable extends TodosTable
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _targetDateMeta = const VerificationMeta('targetDate');
|
||||||
GeneratedDateTimeColumn _targetDate;
|
GeneratedDateTimeColumn _targetDate;
|
||||||
@override
|
@override
|
||||||
GeneratedDateTimeColumn get targetDate =>
|
GeneratedDateTimeColumn get targetDate =>
|
||||||
|
@ -140,6 +144,7 @@ class $TodosTableTable extends TodosTable
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _categoryMeta = const VerificationMeta('category');
|
||||||
GeneratedIntColumn _category;
|
GeneratedIntColumn _category;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get category => _category ??= _constructCategory();
|
GeneratedIntColumn get category => _category ??= _constructCategory();
|
||||||
|
@ -161,12 +166,24 @@ class $TodosTableTable extends TodosTable
|
||||||
@override
|
@override
|
||||||
final String actualTableName = 'todos';
|
final String actualTableName = 'todos';
|
||||||
@override
|
@override
|
||||||
bool validateIntegrity(TodoEntry instance, bool isInserting) =>
|
VerificationContext validateIntegrity(TodoEntry instance, bool isInserting) =>
|
||||||
id.isAcceptableValue(instance.id, isInserting) &&
|
VerificationContext()
|
||||||
title.isAcceptableValue(instance.title, isInserting) &&
|
..handle(
|
||||||
content.isAcceptableValue(instance.content, isInserting) &&
|
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
|
||||||
targetDate.isAcceptableValue(instance.targetDate, isInserting) &&
|
..handle(_titleMeta,
|
||||||
category.isAcceptableValue(instance.category, isInserting);
|
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
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
|
@ -259,6 +276,7 @@ class $CategoriesTable extends Categories
|
||||||
final GeneratedDatabase _db;
|
final GeneratedDatabase _db;
|
||||||
final String _alias;
|
final String _alias;
|
||||||
$CategoriesTable(this._db, [this._alias]);
|
$CategoriesTable(this._db, [this._alias]);
|
||||||
|
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||||
GeneratedIntColumn _id;
|
GeneratedIntColumn _id;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get id => _id ??= _constructId();
|
GeneratedIntColumn get id => _id ??= _constructId();
|
||||||
|
@ -266,6 +284,8 @@ class $CategoriesTable extends Categories
|
||||||
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _descriptionMeta =
|
||||||
|
const VerificationMeta('description');
|
||||||
GeneratedTextColumn _description;
|
GeneratedTextColumn _description;
|
||||||
@override
|
@override
|
||||||
GeneratedTextColumn get description =>
|
GeneratedTextColumn get description =>
|
||||||
|
@ -284,9 +304,14 @@ class $CategoriesTable extends Categories
|
||||||
@override
|
@override
|
||||||
final String actualTableName = 'categories';
|
final String actualTableName = 'categories';
|
||||||
@override
|
@override
|
||||||
bool validateIntegrity(Category instance, bool isInserting) =>
|
VerificationContext validateIntegrity(Category instance, bool isInserting) =>
|
||||||
id.isAcceptableValue(instance.id, isInserting) &&
|
VerificationContext()
|
||||||
description.isAcceptableValue(instance.description, isInserting);
|
..handle(
|
||||||
|
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
|
||||||
|
..handle(
|
||||||
|
_descriptionMeta,
|
||||||
|
description.isAcceptableValue(
|
||||||
|
instance.description, isInserting, _descriptionMeta));
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
|
@ -413,6 +438,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
||||||
final GeneratedDatabase _db;
|
final GeneratedDatabase _db;
|
||||||
final String _alias;
|
final String _alias;
|
||||||
$UsersTable(this._db, [this._alias]);
|
$UsersTable(this._db, [this._alias]);
|
||||||
|
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||||
GeneratedIntColumn _id;
|
GeneratedIntColumn _id;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get id => _id ??= _constructId();
|
GeneratedIntColumn get id => _id ??= _constructId();
|
||||||
|
@ -420,6 +446,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
||||||
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
return GeneratedIntColumn('id', $tableName, false, hasAutoIncrement: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _nameMeta = const VerificationMeta('name');
|
||||||
GeneratedTextColumn _name;
|
GeneratedTextColumn _name;
|
||||||
@override
|
@override
|
||||||
GeneratedTextColumn get name => _name ??= _constructName();
|
GeneratedTextColumn get name => _name ??= _constructName();
|
||||||
|
@ -428,6 +455,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
||||||
minTextLength: 6, maxTextLength: 32);
|
minTextLength: 6, maxTextLength: 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _isAwesomeMeta = const VerificationMeta('isAwesome');
|
||||||
GeneratedBoolColumn _isAwesome;
|
GeneratedBoolColumn _isAwesome;
|
||||||
@override
|
@override
|
||||||
GeneratedBoolColumn get isAwesome => _isAwesome ??= _constructIsAwesome();
|
GeneratedBoolColumn get isAwesome => _isAwesome ??= _constructIsAwesome();
|
||||||
|
@ -436,6 +464,8 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
||||||
defaultValue: const Constant(true));
|
defaultValue: const Constant(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _profilePictureMeta =
|
||||||
|
const VerificationMeta('profilePicture');
|
||||||
GeneratedBlobColumn _profilePicture;
|
GeneratedBlobColumn _profilePicture;
|
||||||
@override
|
@override
|
||||||
GeneratedBlobColumn get profilePicture =>
|
GeneratedBlobColumn get profilePicture =>
|
||||||
|
@ -448,6 +478,8 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _creationTimeMeta =
|
||||||
|
const VerificationMeta('creationTime');
|
||||||
GeneratedDateTimeColumn _creationTime;
|
GeneratedDateTimeColumn _creationTime;
|
||||||
@override
|
@override
|
||||||
GeneratedDateTimeColumn get creationTime =>
|
GeneratedDateTimeColumn get creationTime =>
|
||||||
|
@ -467,12 +499,24 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
||||||
@override
|
@override
|
||||||
final String actualTableName = 'users';
|
final String actualTableName = 'users';
|
||||||
@override
|
@override
|
||||||
bool validateIntegrity(User instance, bool isInserting) =>
|
VerificationContext validateIntegrity(User instance, bool isInserting) =>
|
||||||
id.isAcceptableValue(instance.id, isInserting) &&
|
VerificationContext()
|
||||||
name.isAcceptableValue(instance.name, isInserting) &&
|
..handle(
|
||||||
isAwesome.isAcceptableValue(instance.isAwesome, isInserting) &&
|
_idMeta, id.isAcceptableValue(instance.id, isInserting, _idMeta))
|
||||||
profilePicture.isAcceptableValue(instance.profilePicture, isInserting) &&
|
..handle(_nameMeta,
|
||||||
creationTime.isAcceptableValue(instance.creationTime, isInserting);
|
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
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
|
@ -563,6 +607,7 @@ class $SharedTodosTable extends SharedTodos
|
||||||
final GeneratedDatabase _db;
|
final GeneratedDatabase _db;
|
||||||
final String _alias;
|
final String _alias;
|
||||||
$SharedTodosTable(this._db, [this._alias]);
|
$SharedTodosTable(this._db, [this._alias]);
|
||||||
|
final VerificationMeta _todoMeta = const VerificationMeta('todo');
|
||||||
GeneratedIntColumn _todo;
|
GeneratedIntColumn _todo;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get todo => _todo ??= _constructTodo();
|
GeneratedIntColumn get todo => _todo ??= _constructTodo();
|
||||||
|
@ -574,6 +619,7 @@ class $SharedTodosTable extends SharedTodos
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _userMeta = const VerificationMeta('user');
|
||||||
GeneratedIntColumn _user;
|
GeneratedIntColumn _user;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get user => _user ??= _constructUser();
|
GeneratedIntColumn get user => _user ??= _constructUser();
|
||||||
|
@ -594,9 +640,13 @@ class $SharedTodosTable extends SharedTodos
|
||||||
@override
|
@override
|
||||||
final String actualTableName = 'shared_todos';
|
final String actualTableName = 'shared_todos';
|
||||||
@override
|
@override
|
||||||
bool validateIntegrity(SharedTodo instance, bool isInserting) =>
|
VerificationContext validateIntegrity(
|
||||||
todo.isAcceptableValue(instance.todo, isInserting) &&
|
SharedTodo instance, bool isInserting) =>
|
||||||
user.isAcceptableValue(instance.user, isInserting);
|
VerificationContext()
|
||||||
|
..handle(_todoMeta,
|
||||||
|
todo.isAcceptableValue(instance.todo, isInserting, _todoMeta))
|
||||||
|
..handle(_userMeta,
|
||||||
|
user.isAcceptableValue(instance.user, isInserting, _userMeta));
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {todo, user};
|
Set<GeneratedColumn> get $primaryKey => {todo, user};
|
||||||
@override
|
@override
|
||||||
|
@ -686,6 +736,8 @@ class $TableWithoutPKTable extends TableWithoutPK
|
||||||
final GeneratedDatabase _db;
|
final GeneratedDatabase _db;
|
||||||
final String _alias;
|
final String _alias;
|
||||||
$TableWithoutPKTable(this._db, [this._alias]);
|
$TableWithoutPKTable(this._db, [this._alias]);
|
||||||
|
final VerificationMeta _notReallyAnIdMeta =
|
||||||
|
const VerificationMeta('notReallyAnId');
|
||||||
GeneratedIntColumn _notReallyAnId;
|
GeneratedIntColumn _notReallyAnId;
|
||||||
@override
|
@override
|
||||||
GeneratedIntColumn get notReallyAnId =>
|
GeneratedIntColumn get notReallyAnId =>
|
||||||
|
@ -698,6 +750,7 @@ class $TableWithoutPKTable extends TableWithoutPK
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final VerificationMeta _someFloatMeta = const VerificationMeta('someFloat');
|
||||||
GeneratedRealColumn _someFloat;
|
GeneratedRealColumn _someFloat;
|
||||||
@override
|
@override
|
||||||
GeneratedRealColumn get someFloat => _someFloat ??= _constructSomeFloat();
|
GeneratedRealColumn get someFloat => _someFloat ??= _constructSomeFloat();
|
||||||
|
@ -718,9 +771,17 @@ class $TableWithoutPKTable extends TableWithoutPK
|
||||||
@override
|
@override
|
||||||
final String actualTableName = 'table_without_p_k';
|
final String actualTableName = 'table_without_p_k';
|
||||||
@override
|
@override
|
||||||
bool validateIntegrity(TableWithoutPKData instance, bool isInserting) =>
|
VerificationContext validateIntegrity(
|
||||||
notReallyAnId.isAcceptableValue(instance.notReallyAnId, isInserting) &&
|
TableWithoutPKData instance, bool isInserting) =>
|
||||||
someFloat.isAcceptableValue(instance.someFloat, isInserting);
|
VerificationContext()
|
||||||
|
..handle(
|
||||||
|
_notReallyAnIdMeta,
|
||||||
|
notReallyAnId.isAcceptableValue(
|
||||||
|
instance.notReallyAnId, isInserting, _notReallyAnIdMeta))
|
||||||
|
..handle(
|
||||||
|
_someFloatMeta,
|
||||||
|
someFloat.isAcceptableValue(
|
||||||
|
instance.someFloat, isInserting, _someFloatMeta));
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => <GeneratedColumn>{};
|
Set<GeneratedColumn> get $primaryKey => <GeneratedColumn>{};
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ class TableWriter {
|
||||||
|
|
||||||
// Generate the columns
|
// Generate the columns
|
||||||
for (var column in table.columns) {
|
for (var column in table.columns) {
|
||||||
|
_writeColumnVerificationMeta(buffer, column);
|
||||||
_writeColumnGetter(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) {
|
void _writeValidityCheckMethod(StringBuffer buffer) {
|
||||||
final dataClass = table.dartTypeName;
|
final dataClass = table.dartTypeName;
|
||||||
|
|
||||||
buffer.write(
|
buffer.write('@override\nVerificationContext validateIntegrity'
|
||||||
'@override\nbool validateIntegrity($dataClass instance, bool isInserting) => ');
|
'($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 getterName = column.dartGetterName;
|
||||||
|
final metaName = _fieldNameForColumnMeta(column);
|
||||||
|
|
||||||
// generated columns have a isAcceptableValue(T value, bool duringInsert)
|
// ..handle(_meta, c.isAcceptableValue(instance.c, insert, _meta))
|
||||||
// method
|
buffer.write('..handle($metaName, $getterName.isAcceptableValue('
|
||||||
|
'instance.$getterName, isInserting, $metaName))');
|
||||||
|
}
|
||||||
|
|
||||||
return '$getterName.isAcceptableValue(instance.$getterName, isInserting)';
|
buffer.write(';\n');
|
||||||
}).join('&&');
|
}
|
||||||
|
|
||||||
buffer..write(validationCode)..write(';\n');
|
String _fieldNameForColumnMeta(SpecifiedColumn column) {
|
||||||
|
return '_${column.dartGetterName}Meta';
|
||||||
}
|
}
|
||||||
|
|
||||||
void _writePrimaryKeyOverride(StringBuffer buffer) {
|
void _writePrimaryKeyOverride(StringBuffer buffer) {
|
||||||
|
|
Loading…
Reference in New Issue